diff --git a/Makefile b/Makefile index f5f4041..6ff1532 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,41 @@ -CC = clang -CXX = clang++ -AR = ar -BUILD_TYPE = debug -CSTD = -std=gnu11 -CXXSTD = -std=gnu++11 -CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc -LIBFLAGS = -fPIC -KERNEL = $(shell uname -s) -MACHINE = $(shell uname -m) -PLATFORM = $(KERNEL)_$(MACHINE) -TEST_INCLUDE = -Isrc $(shell find tests -type d | xargs -I{} echo -n "-I{} ") -TEST_SRC = $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ") -TEST_C_SRC = src/wapp.c $(TEST_SRC) -TEST_CXX_SRC = $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ") -BUILD_DIR = libwapp-build/$(PLATFORM)-$(BUILD_TYPE) -LIB_NAME = wapp -OBJ_OUT = $(BUILD_DIR)/$(LIB_NAME).o -LIB_OUT = $(BUILD_DIR)/lib$(LIB_NAME).a -TEST_C_OUT = $(BUILD_DIR)/wapptest -TEST_CXX_OUT = $(BUILD_DIR)/wapptestcc +# External variables +CC ?= clang +CXX ?= clang++ +AR ?= ar +BUILD_TYPE ?= Debug +BUILD_DIR ?= libwapp-build/$(PLATFORM)-$(BUILD_TYPE) +INSTALL_PREFIX ?= dist -ifeq ($(BUILD_TYPE),debug) +# Internal variables +override CFLAGS = -Wall -Wextra -Werror -pedantic -Isrc +override LIBFLAGS = -fPIC +override ABS_INSTALL_PREFIX != readlink -f $(INSTALL_PREFIX) +override CSTD := -std=gnu11 +override CXXSTD := -std=gnu++11 +override KERNEL := $(shell uname -s) +override MACHINE := $(shell uname -m) +override PLATFORM := $(KERNEL)_$(MACHINE) +override TEST_INCLUDE := -Isrc $(shell find tests -type d | xargs -I{} echo -n "-I{} ") +override TEST_SRC := $(shell find tests -type f -name "*.c" | xargs -I{} echo -n "{} ") +override TEST_C_SRC := src/wapp.c $(TEST_SRC) +override TEST_CXX_SRC := $(shell find tests -type f -name "*.cc" | xargs -I{} echo -n "{} ") +override LIB_NAME := wapp +override OBJ_OUT := $(BUILD_DIR)/$(LIB_NAME).o +override LIB_OUT := $(BUILD_DIR)/lib$(LIB_NAME).a +override TEST_C_OUT := $(BUILD_DIR)/wapptest +override TEST_CXX_OUT := $(BUILD_DIR)/wapptestcc +override INCLUDE_INSTALL := $(ABS_INSTALL_PREFIX)/include/$(LIB_NAME) +override LIB_INSTALL := $(ABS_INSTALL_PREFIX)/lib +override HEADER_INSTALL_CMD := scripts/header_install.sh + +ifeq ($(BUILD_TYPE),Debug) CFLAGS += -g -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT -else ifeq ($(BUILD_TYPE),release) +else ifeq ($(BUILD_TYPE),RelWithDebInfo) + CFLAGS += -g -O2 -fsanitize=address,undefined -DWAPP_DEBUG_ASSERT +else ifeq ($(BUILD_TYPE),Release) CFLAGS += -O3 else - $(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'debug' or 'release') + $(error Invalid BUILD type '$(BUILD_TYPE)'. Use 'Debug', 'RelWithDebInfo' or 'Release') endif ifeq ($(CC),gcc) @@ -33,13 +43,56 @@ ifeq ($(CC),gcc) export ASAN_OPTIONS=verify_asan_link_order=0 endif -.PHONY: all clean builddir build-test run-test codegen build-lib full prng testing uuid core primitives +.PHONY: help full prng testing uuid core primitives all clean builddir build-test run-test codegen install build-lib -all: clean builddir codegen run-c-test full run-cc-test +help: + @echo "Available build variables:" + @echo " CC C compiler to use (Default: clang)." + @echo " CXX C++ compiler to use (Default: clang++)." + @echo " AR Archiving utility to use for building static libraries (Default: ar)." + @echo " BUILD_TYPE Build type. Choose from \`Debug\`, \`RelWithDebInfo\` or \`Release\` (Default: Debug)." + @echo " BUILD_DIR Directory where build files will be written." + @echo " INSTALL_PREFIX Prefix where library and include files will be installed." + @echo + @echo "Available targets:" + @echo " make full Build and install the full wapp library." + @echo " make core Build and install only the \`core\` component of the wapp library with all its dependencies." + @echo " make prng Build and install only the \`prng\` component of the wapp library with all its dependencies." + @echo " make uuid Build and install only the \`uuid\` component of the wapp library with all its dependencies." + @echo " make testing Build and install only the \`testing\` component of the wapp library with all its dependencies." + @echo " make primitives Build and install only the \`primitives\` component of the wapp library with all its dependencies." + @echo " make clean Clean build directory." + @echo " make help Print this help message and exit." + +full: LIB_SRC = src/wapp.c +full: INCLUDES = common core primitives prng testing uuid +full: install + +prng: LIB_SRC = src/prng/wapp_prng.c +prng: INCLUDES = common prng +prng: install + +testing: LIB_SRC = src/testing/wapp_testing.c +testing: INCLUDES = common core testing +testing: install + +uuid: LIB_SRC = src/uuid/wapp_uuid.c +uuid: INCLUDES = common primitives prng +uuid: install + +core: LIB_SRC = src/core/wapp_core.c +core: INCLUDES = common core primitives +core: install + +primitives: LIB_SRC = src/core/wapp_primitives.c +primitives: INCLUDES = common primitives +primitives: install clean: @rm -rf $(BUILD_DIR) +all: clean builddir codegen run-c-test full run-cc-test + builddir: @mkdir -p $(BUILD_DIR) @@ -62,25 +115,13 @@ run-cc-test: build-cc-test codegen: python3 -m codegen -build-lib: +install: build-lib + @mkdir -p $(LIB_INSTALL) + @cp -v $(LIB_OUT) $(LIB_INSTALL) + @mkdir -p $(INCLUDE_INSTALL) + @bash $(HEADER_INSTALL_CMD) $(LIB_SRC) $(INCLUDE_INSTALL) $(INCLUDES) + +build-lib: builddir $(CC) -c $(CSTD) $(CFLAGS) $(LIBFLAGS) $(LIB_SRC) -o $(OBJ_OUT) $(AR) r $(LIB_OUT) $(OBJ_OUT) @rm $(OBJ_OUT) - -full: LIB_SRC = src/wapp.c -full: build-lib - -prng: LIB_SRC = src/prng/wapp_prng.c -prng: build-lib - -testing: LIB_SRC = src/testing/wapp_testing.c -testing: build-lib - -uuid: LIB_SRC = src/uuid/wapp_uuid.c -uuid: build-lib - -core: LIB_SRC = src/core/wapp_core.c -core: build-lib - -primitives: LIB_SRC = src/core/wapp_primitives.c -primitives: build-lib diff --git a/build b/build index 94512f0..8d16d0e 100755 --- a/build +++ b/build @@ -1,14 +1,36 @@ #!/bin/bash -BUILD_TYPE="debug" +# Colors +RED="\033[0;31m" +BOLD="\033[1m" +NC="\033[0m" # No Color + +BUILD_TYPE="Debug" +ACCEPTED_BUILD_TYPES=("RelWithDebInfo" "Debug" "Release") KERNEL="$(uname -s)" ARGS="" +join_array_elements() { + local IFS="," + echo "$*" +} + +print_usage() { + echo -e "Usage: build [-b build_type] ..." + echo -e " Options:" + echo -e " -b, --build-type Choose from $(join_array_elements ${ACCEPTED_BUILD_TYPES[*]}) (Default: Debug)." + echo -e " -h, --help Print this message and exit" +} + while [[ $# > 0 ]];do case $1 in - --release) - BUILD_TYPE="release" - shift + -b|--build-type) + BUILD_TYPE="$2" + shift 2 + ;; + -h|--help) + print_usage + exit 0 ;; *|-*|--*) rest=("$@") @@ -18,15 +40,24 @@ while [[ $# > 0 ]];do esac done -if [[ $KERNEL == "Darwin" ]]; then - if [[ ! -d .venv ]]; then - python3 -m venv .venv - fi - - source .venv/bin/activate - pip install scan-build - intercept-build make CC=intercept-cc CXX=intercept-c++ BUILD_TYPE=$BUILD_TYPE $ARGS - deactivate -else - bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS +# Compare build type against array +# From this: https://www.baeldung.com/linux/check-bash-array-contains-value#using-anifcondition-with-aregex-pattern +build_regex="\<${BUILD_TYPE}\>" +if [[ ! ${ACCEPTED_BUILD_TYPES[@]} =~ $build_regex ]]; then + echo -e "${RED}${BOLD}Unknown build type: ${BUILD_TYPE}${NC}\n" + print_usage + exit 1 +fi + +if [[ $KERNEL == "Darwin" ]]; then + if [[ ! -d .venv ]]; then + python3 -m venv .venv + fi + + source .venv/bin/activate + pip install scan-build + intercept-build make CC=intercept-cc CXX=intercept-c++ BUILD_TYPE=$BUILD_TYPE $ARGS + deactivate +else + bear -- make BUILD_TYPE=$BUILD_TYPE $ARGS fi diff --git a/scripts/header_install.sh b/scripts/header_install.sh new file mode 100644 index 0000000..bf11331 --- /dev/null +++ b/scripts/header_install.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +SCRIPT_DIR="$(dirname $0)" +LIB_SRC="$1" +INSTALL_PREFIX="$2" +shift 2 +INCLUDES="$@" + +mkdir -p "$INSTALL_PREFIX" + +BASE_INCLUDE_DIR="$(dirname "$LIB_SRC")" +find $BASE_INCLUDE_DIR -maxdepth 1 -type f -name "*.h" -exec cp -v {} "$INSTALL_PREFIX" \; + +cd "$SCRIPT_DIR/../src" +for INCLUDE in $INCLUDES; do + for f in $(find "$INCLUDE" -type f -name "*.h"); do + DST="$INSTALL_PREFIX/$(dirname $f)" + mkdir -p "$DST" + cp -v "$f" "$DST" + done +done