net-tools/configure
lohhiiccc 0ddbb95bad refactor: improve build configuration and output
- Track libicmp sources for proper dependency rebuilds
- Remove verbose build output (CC and LINK messages)
- Fix typo in help message (uninstal -> uninstall)
- Pass compiler flags to libicmp build
- Align configuration summary output
2026-02-08 00:35:28 +01:00

704 lines
16 KiB
Bash
Executable file

#!/usr/bin/env bash
# configure - Configuration script for ft_ping
# Generates build.mk with build configuration
set -e
# CONSTANTS
SCRIPT_VERSION="1.0.0"
PROJECT_NAME="ft_ping"
BUILD_MK="build.mk"
LIBICMP_DIR="libicmp"
LIBICMP_MAKEFILE="Makefile"
# Default values
DEFAULT_PREFIX="/usr/local"
DEFAULT_CC="clang"
DEFAULT_LIBICMP_MODE="auto"
DEFAULT_LIBRARY_TYPE="shared"
DEFAULT_ENABLE_TESTS="no"
DEFAULT_ENABLE_DEBUG="no"
DEFAULT_ENABLE_SANITIZERS="no"
DEFAULT_ENABLE_LTO="no"
DEFAULT_ENABLE_STRICT="no"
DEFAULT_SUDO_TESTS="yes"
DEFAULT_INSTALL_LIBICMP="no"
# Current configuration
PREFIX="$DEFAULT_PREFIX"
CC="$DEFAULT_CC"
LIBICMP_MODE="$DEFAULT_LIBICMP_MODE"
LIBRARY_TYPE="$DEFAULT_LIBRARY_TYPE"
LIBRARY_PREFERENCE="prefer" # prefer, only
ENABLE_TESTS="$DEFAULT_ENABLE_TESTS"
ENABLE_DEBUG="$DEFAULT_ENABLE_DEBUG"
ENABLE_SANITIZERS="$DEFAULT_ENABLE_SANITIZERS"
ENABLE_LTO="$DEFAULT_ENABLE_LTO"
ENABLE_STRICT="$DEFAULT_ENABLE_STRICT"
SUDO_TESTS="$DEFAULT_SUDO_TESTS"
INSTALL_LIBICMP="$DEFAULT_INSTALL_LIBICMP"
VERBOSE="no"
QUIET="no"
# User-provided flags
USER_CFLAGS=""
USER_LDFLAGS=""
USER_CPPFLAGS=""
# Derived paths
BINDIR=""
LIBDIR=""
INCLUDEDIR=""
LIBICMP_PREFIX=""
# HELPER FUNCTIONS
info() {
if [ "$QUIET" != "yes" ]; then
echo -e "[INFO] $*"
fi
}
success() {
if [ "$QUIET" != "yes" ]; then
echo -e "[OK] $*"
fi
}
warn() {
echo -e "[WARN] $*" >&2
}
error() {
echo -e "[ERROR] $*" >&2
}
fatal() {
error "$@"
exit 1
}
verbose() {
if [ "$VERBOSE" = "yes" ]; then
echo -e "[VERBOSE] $*"
fi
}
# HELP
show_help() {
cat << EOF
Usage: ./configure [OPTIONS]
Configuration script for $PROJECT_NAME v$SCRIPT_VERSION
libicmp Options:
--with-system-libicmp Use system-installed libicmp (fail if not found)
--with-local-libicmp Build local libicmp (ignore system version)
--auto-libicmp Auto-detect libicmp (default)
Library Type Options:
--prefer-static Prefer static library (.a) with fallback (default if local)
--prefer-shared Prefer shared library (.so) with fallback (default if system)
--static-only Require static library (fail if unavailable)
--shared-only Require shared library (fail if unavailable)
Build Options:
--enable-debug Enable debug symbols (-g -O0)
--disable-debug Disable debug (default, -O2)
--enable-sanitizers Enable AddressSanitizer and UndefinedBehaviorSanitizer
--enable-lto Enable Link Time Optimization
--strict Enable strict warnings (-Wpedantic -Wconversion etc.)
Installation Paths:
--prefix=PREFIX Installation prefix (default: $DEFAULT_PREFIX)
--bindir=DIR Binary directory (default: PREFIX/bin)
--libdir=DIR Library directory (default: PREFIX/lib)
--includedir=DIR Include directory (default: PREFIX/include)
--libicmp-prefix=PREFIX libicmp installation prefix (default: same as --prefix)
Test Options:
--enable-tests Build tests (requires criterion)
--disable-tests Don't build tests (default)
--enable-sudo-tests Tests require sudo (default)
--disable-sudo-tests Tests without sudo (requires capabilities)
libicmp Installation:
--install-libicmp Install libicmp to system (if built locally)
--no-install-libicmp Don't install libicmp (default)
Compiler Options:
CC=compiler Specify compiler (default: $DEFAULT_CC)
CFLAGS="flags" Additional compilation flags
CPPFLAGS="flags" Additional preprocessor flags
LDFLAGS="flags" Additional linker flags
Other Options:
--help, -h Show this help message
--version, -v Show version
--verbose Verbose output during configuration
--quiet, -q Quiet mode (minimal output)
Examples:
./configure
./configure --with-local-libicmp --static-only
./configure --enable-debug --enable-sanitizers --enable-tests
./configure --prefix=/opt/ft_ping --install-libicmp
./configure CC=gcc --strict
EOF
exit 0
}
show_version() {
echo "$PROJECT_NAME configure script version $SCRIPT_VERSION"
exit 0
}
# ARGUMENT PARSING
parse_arguments() {
while [ $# -gt 0 ]; do
case "$1" in
--help|-h)
show_help
;;
--version|-v)
show_version
;;
--verbose)
VERBOSE="yes"
;;
--quiet|-q)
QUIET="yes"
;;
# libicmp mode
--with-system-libicmp)
LIBICMP_MODE="system"
;;
--with-local-libicmp)
LIBICMP_MODE="local"
;;
--auto-libicmp)
LIBICMP_MODE="auto"
;;
# Library type
--prefer-static)
LIBRARY_TYPE="static"
LIBRARY_PREFERENCE="prefer"
;;
--prefer-shared)
LIBRARY_TYPE="shared"
LIBRARY_PREFERENCE="prefer"
;;
--static-only)
LIBRARY_TYPE="static"
LIBRARY_PREFERENCE="only"
;;
--shared-only)
LIBRARY_TYPE="shared"
LIBRARY_PREFERENCE="only"
;;
# Build options
--enable-debug)
ENABLE_DEBUG="yes"
;;
--disable-debug)
ENABLE_DEBUG="no"
;;
--enable-sanitizers)
ENABLE_SANITIZERS="yes"
;;
--enable-lto)
ENABLE_LTO="yes"
;;
--strict)
ENABLE_STRICT="yes"
;;
# Installation paths
--prefix=*)
PREFIX="${1#*=}"
;;
--bindir=*)
BINDIR="${1#*=}"
;;
--libdir=*)
LIBDIR="${1#*=}"
;;
--includedir=*)
INCLUDEDIR="${1#*=}"
;;
--libicmp-prefix=*)
LIBICMP_PREFIX="${1#*=}"
;;
# Tests
--enable-tests)
ENABLE_TESTS="yes"
;;
--disable-tests)
ENABLE_TESTS="no"
;;
--enable-sudo-tests)
SUDO_TESTS="yes"
;;
--disable-sudo-tests)
SUDO_TESTS="no"
;;
# libicmp installation
--install-libicmp)
INSTALL_LIBICMP="yes"
;;
--no-install-libicmp)
INSTALL_LIBICMP="no"
;;
# Compiler variables
CC=*)
CC="${1#*=}"
;;
CFLAGS=*)
USER_CFLAGS="${1#*=}"
;;
CPPFLAGS=*)
USER_CPPFLAGS="${1#*=}"
;;
LDFLAGS=*)
USER_LDFLAGS="${1#*=}"
;;
*)
fatal "Unknown option: $1\nTry './configure --help' for more information."
;;
esac
shift
done
}
# VALIDATION
validate_configuration() {
verbose "Validating configuration..."
# Check for conflicting options
if [ "$LIBICMP_MODE" = "system" ] && [ "$INSTALL_LIBICMP" = "yes" ]; then
warn "Option --install-libicmp ignored when using system libicmp"
INSTALL_LIBICMP="no"
fi
# Set derived paths
[ -z "$BINDIR" ] && BINDIR="$PREFIX/bin"
[ -z "$LIBDIR" ] && LIBDIR="$PREFIX/lib"
[ -z "$INCLUDEDIR" ] && INCLUDEDIR="$PREFIX/include"
[ -z "$LIBICMP_PREFIX" ] && LIBICMP_PREFIX="$PREFIX"
verbose "PREFIX=$PREFIX"
verbose "BINDIR=$BINDIR"
verbose "LIBDIR=$LIBDIR"
verbose "INCLUDEDIR=$INCLUDEDIR"
}
# DETECTION
check_command() {
local cmd="$1"
if command -v "$cmd" >/dev/null 2>&1; then
return 0
else
return 1
fi
}
check_compiler() {
info "Checking for compiler: $CC"
if ! check_command "$CC"; then
fatal "Compiler '$CC' not found"
fi
# Get compiler version
local cc_version
cc_version=$($CC --version 2>&1 | head -n1)
success "Found $cc_version"
verbose "Compiler: $CC"
verbose "Version: $cc_version"
}
detect_system_libicmp() {
local system_libdir="${PREFIX}/lib"
local system_includedir="${PREFIX}/include"
verbose "Searching for system libicmp in $system_libdir"
SYSTEM_LIBICMP_STATIC="${system_libdir}/libicmp.a"
SYSTEM_LIBICMP_SHARED="${system_libdir}/libicmp.so"
SYSTEM_ICMP_H="${system_includedir}/icmp.h"
HAS_STATIC="no"
HAS_SHARED="no"
HAS_HEADERS="no"
if [ -f "$SYSTEM_LIBICMP_STATIC" ]; then
HAS_STATIC="yes"
verbose "Found static library: $SYSTEM_LIBICMP_STATIC"
fi
if [ -f "$SYSTEM_LIBICMP_SHARED" ]; then
HAS_SHARED="yes"
verbose "Found shared library: $SYSTEM_LIBICMP_SHARED"
fi
if [ -f "$SYSTEM_ICMP_H" ]; then
HAS_HEADERS="yes"
verbose "Found headers: $SYSTEM_ICMP_H"
fi
if [ "$HAS_HEADERS" = "yes" ] && { [ "$HAS_STATIC" = "yes" ] || [ "$HAS_SHARED" = "yes" ]; }; then
return 0 # System libicmp found
else
return 1 # System libicmp not found
fi
}
decide_libicmp_source() {
info "Determining libicmp source..."
case "$LIBICMP_MODE" in
system)
verbose "Mode: force system libicmp"
if detect_system_libicmp; then
success "Using system-installed libicmp from $PREFIX/lib"
USE_SYSTEM_LIBICMP="yes"
BUILD_LOCAL_LIBICMP="no"
else
fatal "System libicmp not found but --with-system-libicmp specified"
fi
;;
local)
verbose "Mode: force local build"
success "Building local libicmp from $LIBICMP_DIR/"
USE_SYSTEM_LIBICMP="no"
BUILD_LOCAL_LIBICMP="yes"
;;
auto)
verbose "Mode: auto-detect"
if detect_system_libicmp; then
success "Using system-installed libicmp from $PREFIX/lib"
USE_SYSTEM_LIBICMP="yes"
BUILD_LOCAL_LIBICMP="no"
else
info "System libicmp not found, will build local version"
USE_SYSTEM_LIBICMP="no"
BUILD_LOCAL_LIBICMP="yes"
fi
;;
esac
}
determine_library_type() {
info "Determining library type..."
if [ "$USE_SYSTEM_LIBICMP" = "yes" ]; then
# System library - check what's available
case "$LIBRARY_TYPE" in
static)
if [ "$HAS_STATIC" = "yes" ]; then
FINAL_LIBRARY_TYPE="static"
LIBICMP_PATH="$SYSTEM_LIBICMP_STATIC"
success "Using static system library"
elif [ "$LIBRARY_PREFERENCE" = "only" ]; then
fatal "Static library required but only shared library found"
elif [ "$HAS_SHARED" = "yes" ]; then
warn "Static library not found, falling back to shared"
FINAL_LIBRARY_TYPE="shared"
LIBICMP_PATH="$SYSTEM_LIBICMP_SHARED"
else
fatal "No suitable library found"
fi
;;
shared)
if [ "$HAS_SHARED" = "yes" ]; then
FINAL_LIBRARY_TYPE="shared"
LIBICMP_PATH="$SYSTEM_LIBICMP_SHARED"
success "Using shared system library"
elif [ "$LIBRARY_PREFERENCE" = "only" ]; then
fatal "Shared library required but only static library found"
elif [ "$HAS_STATIC" = "yes" ]; then
warn "Shared library not found, falling back to static"
FINAL_LIBRARY_TYPE="static"
LIBICMP_PATH="$SYSTEM_LIBICMP_STATIC"
else
fatal "No suitable library found"
fi
;;
esac
else
# Local build - we control what to build
FINAL_LIBRARY_TYPE="$LIBRARY_TYPE"
if [ "$FINAL_LIBRARY_TYPE" = "static" ]; then
LIBICMP_BUILD_STATIC="yes"
LIBICMP_BUILD_SHARED="no"
LIBICMP_PATH="$LIBICMP_DIR/libicmp.a"
success "Will build static library"
else
LIBICMP_BUILD_STATIC="no"
LIBICMP_BUILD_SHARED="yes"
LIBICMP_PATH="$LIBICMP_DIR/libicmp.so"
success "Will build shared library"
fi
fi
verbose "Final library type: $FINAL_LIBRARY_TYPE"
verbose "Library path: $LIBICMP_PATH"
}
check_test_dependencies() {
if [ "$ENABLE_TESTS" = "yes" ]; then
info "Checking test dependencies..."
# Check for criterion library
if ! $CC -lcriterion -o /dev/null -xc - >/dev/null 2>&1 <<< "int main(){return 0;}"; then
warn "Criterion library not found, tests may fail to build"
warn "Install criterion: https://github.com/Snaipe/Criterion"
else
success "Found criterion library"
fi
fi
}
# BUILD.MK GENERATION
generate_build_mk() {
info "Generating $BUILD_MK..."
local timestamp
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Prepare compiler flags
local cflags="-Wall -Wextra -Werror -pipe"
local cppflags="-std=c99 -I includes"
local ldflags=""
local debug_flags=""
local sanitizer_flags=""
local lto_flags=""
local strict_flags=""
# Debug flags
if [ "$ENABLE_DEBUG" = "yes" ]; then
debug_flags="-g -O0 -DDEBUG"
else
debug_flags="-O2 -DNDEBUG"
fi
# Sanitizer flags
if [ "$ENABLE_SANITIZERS" = "yes" ]; then
sanitizer_flags="-fsanitize=address,undefined -fno-omit-frame-pointer"
fi
# LTO flags
if [ "$ENABLE_LTO" = "yes" ]; then
lto_flags="-flto"
fi
# Strict flags
if [ "$ENABLE_STRICT" = "yes" ]; then
strict_flags="-Wpedantic -Wconversion -Wshadow -Wcast-align -Wstrict-prototypes"
fi
# libicmp-specific configuration
if [ "$USE_SYSTEM_LIBICMP" = "yes" ]; then
LIBICMP_DEP=""
ldflags="-licmp"
else
LIBICMP_DEP="$LIBICMP_PATH"
cppflags="$cppflags -I $LIBICMP_DIR/includes"
ldflags="-L$LIBICMP_DIR -licmp"
if [ "$FINAL_LIBRARY_TYPE" = "shared" ] && [ "$INSTALL_LIBICMP" = "yes" ]; then
ldflags="$ldflags -Wl,-rpath,$LIBDIR"
fi
fi
# User-provided flags
if [ -n "$USER_CFLAGS" ]; then
cflags="$cflags $USER_CFLAGS"
fi
if [ -n "$USER_CPPFLAGS" ]; then
cppflags="$cppflags $USER_CPPFLAGS"
fi
if [ -n "$USER_LDFLAGS" ]; then
ldflags="$ldflags $USER_LDFLAGS"
fi
# Write build.mk
cat > "$BUILD_MK" << EOF
# $BUILD_MK - Generated by configure on $timestamp
# DO NOT EDIT - This file is automatically generated
# libicmp Configuration
USE_SYSTEM_LIBICMP = $USE_SYSTEM_LIBICMP
BUILD_LOCAL_LIBICMP = $BUILD_LOCAL_LIBICMP
LIBICMP_TYPE = $FINAL_LIBRARY_TYPE
LIBICMP_DIR = $LIBICMP_DIR
LIBICMP_PATH = $LIBICMP_PATH
LIBICMP_DEP = $LIBICMP_DEP
EOF
if [ "$BUILD_LOCAL_LIBICMP" = "yes" ]; then
local libicmp_cflags="-Wall -Wextra -Werror -pipe -Wpedantic -Wconversion"
local libicmp_cppflags="-std=c99 -I includes -D_POSIX_C_SOURCE=199309L"
libicmp_cflags="$libicmp_cflags $debug_flags"
if [ "$ENABLE_SANITIZERS" = "yes" ]; then
libicmp_cflags="$libicmp_cflags $sanitizer_flags"
fi
if [ "$ENABLE_LTO" = "yes" ]; then
libicmp_cflags="$libicmp_cflags $lto_flags"
fi
cat >> "$BUILD_MK" << EOF
# libicmp build configuration
LIBICMP_BUILD_STATIC = $LIBICMP_BUILD_STATIC
LIBICMP_BUILD_SHARED = $LIBICMP_BUILD_SHARED
LIBICMP_CC = $CC
LIBICMP_CPPFLAGS = $libicmp_cppflags
LIBICMP_CFLAGS = $libicmp_cflags
LIBICMP_BUILD_FLAGS = BUILD_STATIC=\$(LIBICMP_BUILD_STATIC) BUILD_SHARED=\$(LIBICMP_BUILD_SHARED) CC=\$(LIBICMP_CC) CPPFLAGS="\$(LIBICMP_CPPFLAGS)" CFLAGS="\$(LIBICMP_CFLAGS)"
LIBICMP_MAKEFILE = $LIBICMP_MAKEFILE
EOF
fi
cat >> "$BUILD_MK" << EOF
# Compiler Configuration
CC = $CC
CPPFLAGS = $cppflags
CFLAGS = $cflags
LDFLAGS = $ldflags
# Individual flag components (for reference)
DEBUG_FLAGS = $debug_flags
SANITIZER_FLAGS = $sanitizer_flags
LTO_FLAGS = $lto_flags
STRICT_FLAGS = $strict_flags
# Combined flags
CFLAGS += \$(DEBUG_FLAGS) \$(SANITIZER_FLAGS) \$(LTO_FLAGS) \$(STRICT_FLAGS)
LDFLAGS += \$(SANITIZER_FLAGS) \$(LTO_FLAGS)
# Installation Paths
PREFIX = $PREFIX
BINDIR = $BINDIR
LIBDIR = $LIBDIR
INCLUDEDIR = $INCLUDEDIR
# Test Configuration
ENABLE_TESTS = $ENABLE_TESTS
SUDO_TESTS = $SUDO_TESTS
TEST_LDFLAGS = -lcriterion
# Build Options
ENABLE_DEBUG = $ENABLE_DEBUG
ENABLE_SANITIZERS = $ENABLE_SANITIZERS
ENABLE_LTO = $ENABLE_LTO
ENABLE_STRICT = $ENABLE_STRICT
# libicmp Installation (if built locally)
INSTALL_LIBICMP = $INSTALL_LIBICMP
LIBICMP_PREFIX = $LIBICMP_PREFIX
EOF
success "Generated $BUILD_MK"
}
# SUMMARY
show_summary() {
if [ "$QUIET" = "yes" ]; then
return
fi
cat << EOF
------------------------------------------------------------------------
Configuration Summary for $PROJECT_NAME
------------------------------------------------------------------------
libicmp Source: $([ "$USE_SYSTEM_LIBICMP" = "yes" ] && echo "system ($PREFIX/lib)" || echo "local ($LIBICMP_DIR/)")
Library Type: $FINAL_LIBRARY_TYPE
Compiler: $CC
Installation Prefix: $PREFIX
Build Options:
Debug: $ENABLE_DEBUG
Sanitizers: $ENABLE_SANITIZERS
LTO: $ENABLE_LTO
Strict: $ENABLE_STRICT
Tests: $ENABLE_TESTS$([ "$ENABLE_TESTS" = "yes" ] && echo " ($([ "$SUDO_TESTS" = "yes" ] && echo "with sudo" || echo "without sudo"))" || echo "")
EOF
if [ "$BUILD_LOCAL_LIBICMP" = "yes" ]; then
cat << EOF
libicmp Installation: $([ "$INSTALL_LIBICMP" = "yes" ] && echo "yes (to $LIBICMP_PREFIX)" || echo "no (local use only)")
EOF
fi
cat << EOF
Compiler Flags:
CPPFLAGS: $cppflags
CFLAGS: -Wall -Wextra -Werror -pipe $debug_flags $sanitizer_flags $lto_flags $strict_flags
LDFLAGS: $ldflags
------------------------------------------------------------------------
Configuration saved to $BUILD_MK
EOF
}
# MAIN
main() {
parse_arguments "$@"
validate_configuration
check_compiler
decide_libicmp_source
determine_library_type
check_test_dependencies
generate_build_mk
show_summary
exit 0
}
main "$@"