diff --git a/GNUmakefile b/GNUmakefile index 873ce226..c826c5e5 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -6,6 +6,22 @@ # ################################################################################ # +# Basic internal definitios. For a customizable variables and options see below. +# +$(info // The GNU Make $(MAKE_VERSION)) +SHELL := $(shell env bash -c 'echo $$BASH') +MAKE_VERx3 := $(shell printf "%3s%3s%3s" $(subst ., ,$(MAKE_VERSION))) +make_lt_3_81 := $(shell expr "$(MAKE_VERx3)" "<" " 3 81") +ifeq ($(make_lt_3_81),1) +$(error Please use GNU Make 3.81 or above) +endif +make_lt_4_1 := $(shell expr "$(MAKE_VERx3)" "<" " 4 1") +SRC_PROBE_C := $(shell [ -f mdbx.c ] && echo mdbx.c || echo src/osal.c) +SRC_PROBE_CXX := $(shell [ -f mdbx.c++ ] && echo mdbx.c++ || echo src/mdbx.c++) +UNAME := $(shell uname -s 2>/dev/null || echo Unknown) +# +################################################################################ +# # Use `make options` to list the available libmdbx build options. # # Note that the defaults should already be correct for most platforms; @@ -13,39 +29,48 @@ # in README and source code (see src/options.h) if you do. # -SHELL := env bash - # install sandbox DESTDIR ?= - +INSTALL ?= install # install prefixes (inside sandbox) prefix ?= /usr/local mandir ?= $(prefix)/man - # lib/bin suffix for multiarch/biarch, e.g. '.x86_64' suffix ?= -INSTALL ?= install +# toolchain CC ?= gcc CXX ?= g++ CFLAGS_EXTRA ?= LD ?= ld + +# build options MDBX_BUILD_OPTIONS ?=-DNDEBUG=1 MDBX_BUILD_TIMESTAMP ?=$(shell date +%Y-%m-%dT%H:%M:%S%z) -CFLAGS ?= $(strip $(eval CFLAGS := -std=gnu11 -O2 -g -Wall -Werror -Wextra -Wpedantic -ffunction-sections -fPIC -fvisibility=hidden -pthread -Wno-error=attributes $$(shell PROBE=$$$$([ -f mdbx.c ] && echo mdbx.c || echo src/osal.c); for opt in -fno-semantic-interposition -Wno-unused-command-line-argument -Wno-tautological-compare; do [ -z "$$$$($(CC) '-DMDBX_BUILD_FLAGS="probe"' $$$${opt} -c $$$${PROBE} -o /dev/null >/dev/null 2>&1 || echo failed)" ] && echo "$$$${opt} "; done)$(CFLAGS_EXTRA))$(CFLAGS)) -# Choosing C++ standard with deferred simple variable expansion trick -CXXSTD ?= $(eval CXXSTD := $$(shell PROBE=$$$$([ -f mdbx.c++ ] && echo mdbx.c++ || echo src/mdbx.c++); for std in gnu++23 c++23 gnu++2b c++2b gnu++20 c++20 gnu++2a c++2a gnu++17 c++17 gnu++1z c++1z gnu++14 c++14 gnu++1y c++1y gnu+11 c++11 gnu++0x c++0x; do $(CXX) -std=$$$${std} -c $$$${PROBE} -o /dev/null 2>probe4std-$$$${std}.err >/dev/null && echo "-std=$$$${std}" && exit; done))$(CXXSTD) -CXXFLAGS = $(strip $(CXXSTD) $(filter-out -std=gnu11,$(CFLAGS))) -# TIP: Try append '--no-as-needed,-lrt' for ability to built with modern glibc, but then use with the old. -LIBS ?= $(shell $(uname2libs)) -LDFLAGS ?= $(shell $(uname2ldflags)) -EXE_LDFLAGS ?= -pthread -LIB_STDCXXFS ?= $(eval LIB_STDCXXFS := $$(shell echo 'int main(void) { MDBX_STD_FILESYSTEM_PATH probe; return probe.is_absolute(); }' | cat mdbx.h++ - | sed $$$$'1s/\xef\xbb\xbf//' | $(CXX) -x c++ $(CXXFLAGS) - -Wl,--allow-multiple-definition -lstdc++fs $(LIBS) $(LDFLAGS) $(EXE_LDFLAGS) -o /dev/null 2>probe4lstdfs.err >/dev/null && echo '-Wl,--allow-multiple-definition -lstdc++fs'))$(LIB_STDCXXFS) +# probe and compose common compiler flags with variable expansion trick (seems this work two times per session for GNU Make 3.81) +CFLAGS ?= $(strip $(eval CFLAGS := -std=gnu11 -O2 -g -Wall -Werror -Wextra -Wpedantic -ffunction-sections -fPIC -fvisibility=hidden -pthread -Wno-error=attributes $$(shell for opt in -fno-semantic-interposition -Wno-unused-command-line-argument -Wno-tautological-compare; do [ -z "$$$$($(CC) '-DMDBX_BUILD_FLAGS="probe"' $$$${opt} -c $(SRC_PROBE_C) -o /dev/null >/dev/null 2>&1 || echo failed)" ] && echo "$$$${opt} "; done)$(CFLAGS_EXTRA))$(CFLAGS)) + +# choosing C++ standard with variable expansion trick (seems this work two times per session for GNU Make 3.81) +CXXSTD ?= $(eval CXXSTD := $$(shell for std in gnu++23 c++23 gnu++2b c++2b gnu++20 c++20 gnu++2a c++2a gnu++17 c++17 gnu++1z c++1z gnu++14 c++14 gnu++1y c++1y gnu+11 c++11 gnu++0x c++0x; do $(CXX) -std=$$$${std} -c $(SRC_PROBE_CXX) -o /dev/null 2>probe4std-$$$${std}.err >/dev/null && echo "-std=$$$${std}" && exit; done))$(CXXSTD) +CXXFLAGS ?= $(strip $(CXXSTD) $(filter-out -std=gnu11,$(CFLAGS))) + +# libraries adn options for linking +EXE_LDFLAGS ?= -pthread +ifeq ($(make_lt_4_1),1) +# don't use variable expansion trick as workaround for bugs of GNU Make before 4.1 +LIBS ?= $(shell $(uname2libs)) +LDFLAGS ?= $(shell $(uname2ldflags)) +LIB_STDCXXFS ?= $(shell echo 'int main(void) { MDBX_STD_FILESYSTEM_PATH probe; return probe.is_absolute(); }' | cat mdbx.h++ - | sed $$'1s/\xef\xbb\xbf//' | $(CXX) -x c++ $(CXXFLAGS) -Wno-error - -Wl,--allow-multiple-definition -lstdc++fs $(LIBS) $(LDFLAGS) $(EXE_LDFLAGS) -o /dev/null 2>probe4lstdfs.err >/dev/null && echo '-Wl,--allow-multiple-definition -lstdc++fs') +else +# using variable expansion trick to avoid repeaded probes +LIBS ?= $(eval LIBS := $$(shell $$(uname2libs)))$(LIBS) +LDFLAGS ?= $(eval LDFLAGS := $$(shell $$(uname2ldflags)))$(LDFLAGS) +LIB_STDCXXFS ?= $(eval LIB_STDCXXFS := $$(shell echo 'int main(void) { MDBX_STD_FILESYSTEM_PATH probe; return probe.is_absolute(); }' | cat mdbx.h++ - | sed $$$$'1s/\xef\xbb\xbf//' | $(CXX) -x c++ $(CXXFLAGS) -Wno-error - -Wl,--allow-multiple-definition -lstdc++fs $(LIBS) $(LDFLAGS) $(EXE_LDFLAGS) -o /dev/null 2>probe4lstdfs.err >/dev/null && echo '-Wl,--allow-multiple-definition -lstdc++fs'))$(LIB_STDCXXFS) +endif ################################################################################ -UNAME := $(shell uname -s 2>/dev/null || echo Unknown) define uname2sosuffix case "$(UNAME)" in Darwin*|Mach*) echo dylib;; @@ -53,33 +78,37 @@ define uname2sosuffix *) echo so;; esac endef + define uname2ldflags case "$(UNAME)" in CYGWIN*|MINGW*|MSYS*|Windows*) - echo '-Wl,--gc-sections,-O1' + echo '-Wl,--gc-sections,-O1'; ;; *) - "$(LD)" --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1' - "$(LD)" --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip' + $(LD) --help 2>/dev/null | grep -q -- --gc-sections && echo '-Wl,--gc-sections,-z,relro,-O1'; + $(LD) --help 2>/dev/null | grep -q -- -dead_strip && echo '-Wl,-dead_strip'; ;; esac endef + +# TIP: try add the'-Wl, --no-as-needed,-lrt' for ability to built with modern glibc, but then use with the old. define uname2libs case "$(UNAME)" in CYGWIN*|MINGW*|MSYS*|Windows*) - echo '-lm -lntdll -lwinmm' + echo '-lm -lntdll -lwinmm'; ;; *SunOS*|*Solaris*) - echo '-lm -lkstat -lrt' + echo '-lm -lkstat -lrt'; ;; *Darwin*|OpenBSD*) - echo '-lm' + echo '-lm'; ;; *) - echo '-lm -lrt' + echo '-lm -lrt'; ;; esac endef + SO_SUFFIX := $(shell $(uname2sosuffix)) HEADERS := mdbx.h mdbx.h++ LIBRARIES := libmdbx.a libmdbx.$(SO_SUFFIX) @@ -161,7 +190,7 @@ show-options: @echo " CC =`which $(CC)` | `$(CC) --version | head -1`" @echo " CFLAGS =$(CFLAGS)" @echo " CXXFLAGS =$(CXXFLAGS)" - @echo " LDFLAGS =$(LDFLAGS) $(LIBS) $(EXE_LDFLAGS)" + @echo " LDFLAGS =$(LDFLAGS) $(LIB_STDCXXFS) $(LIBS) $(EXE_LDFLAGS)" @echo '$(TIP) Use `make help` to listing available targets.' options: