Skip to content

Commit

Permalink
More compiler support and build system work
Browse files Browse the repository at this point in the history
  • Loading branch information
imaami committed Jul 14, 2024
1 parent f6e4578 commit 2b3c3a2
Show file tree
Hide file tree
Showing 11 changed files with 295 additions and 77 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
/.vscode
/build
/src/test
cc-id-macros.h
cc.h
cxx.h
1 change: 1 addition & 0 deletions common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ override __libcanth_common_mk_included__ := 1

include $(lastword $(MAKEFILE_LIST:common.mk=mk/cc.mk))

$(call fyi-once,.about)
$(eval yeet:; $$(call msg,YEET,$$(Y__))@:)
.PHONY: yeet

Expand Down
41 changes: 24 additions & 17 deletions mk/arg.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,50 @@ include $(lastword $(MAKEFILE_LIST:arg.mk=internal.mk))

override __default_O = $(THIS_DIR)

$(call arg_var,DEBUG)
$(call arg_var,O)
$(call arg_var,PKG_CONFIG,pkg-config)
$(call arg_var,Q)
$(call arg_var,V)

$(eval override O=$$(eval override O:=$$$$(patsubst\
//,/,$$$$(or $$$$(realpath $(value O)),$$$$(error \
Output directory "$(value O)" does not exist))/))$$O)

ifneq (1,$(strip $V))
override undefine V
endif
$(call arg_var,PKG_CONFIG,pkg-config)

$(call arg_bool_var,DEBUG)
$(call arg_bool_var,Q)
$(call arg_bool_var,V)

ifdef V
override undefine Q
override undefine nop
else
ifneq (1,$(strip $Q))
override undefine Q
endif
override nop := @:
endif

ifeq (,$(strip $Q$V))
override Y_ := (╯°□°)╯︵ ┻━┻
override Y__ = $(call SGR,38;5;119, $(Y_))
override SGR = $(shell printf '\e[$1m%s\e[m' '$2')
override msg = $(info $($1_pfx)$2)
ifeq (,$Q)
override SGR = $(shell printf '\e[$1m%s\e[m' '$2')
override fyi = $(info $($1_pfx)$2)
override .fyi = $(call pfx-if,$w$w$w$w,$(strip $1))
override fyi-once = $(eval override $1=$$(if $$(filter undefined,$$(origin \
$1)),,$$(eval override undefine $1)$$(call fyi,INFO,$$(call .fyi,$$1))))

override CLEAN_pfx = $(eval override CLEAN_pfx := $$(call SGR,0;35,CLEAN ))$(CLEAN_pfx)
override COMPILE_pfx = $(eval override COMPILE_pfx := $$(call SGR,0;36,COMPILE ))$(COMPILE_pfx)
override CC_pfx = $(eval override CC_pfx := $$(call SGR,0;36,CC ))$(CC_pfx)
override CXX_pfx = $(eval override CXX_pfx := $$(call SGR,0;36,CXX ))$(CXX_pfx)
override INFO_pfx = $(eval override INFO_pfx := $$(call SGR,38;5;213,INFO))$(INFO_pfx)
override INSTALL_pfx = $(eval override INSTALL_pfx := $$(call SGR,1;36,INSTALL ))$(INSTALL_pfx)
override LINK_pfx = $(eval override LINK_pfx := $$(call SGR,1;34,LINK ))$(LINK_pfx)
override STRIP_pfx = $(eval override STRIP_pfx := $$(call SGR,0;33,STRIP ))$(STRIP_pfx)
override SYMLINK_pfx = $(eval override SYMLINK_pfx := $$(call SGR,0;32,SYMLINK ))$(SYMLINK_pfx)
override YEET_pfx = $(eval override YEET_pfx := $$(call SGR,38;5;191,YEET))$(YEET_pfx)
else
override undefine fyi-once
override undefine .fyi
override undefine fyi
endif

ifeq (,$Q$V)
override Y_ := (╯°□°)╯︵ ┻━┻
override Y__ = $(call SGR,38;5;119, $(Y_))
override msg = $(info $($1_pfx)$2)
else
override undefine Y__
override undefine msg
Expand Down
130 changes: 106 additions & 24 deletions mk/cc.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,22 @@ override __libcanth_cc_mk_included__ := 1

include $(lastword $(MAKEFILE_LIST:cc.mk=arg.mk))

override __default_CPPFLAGS = $(if $(DEBUG),,-DNDEBUG)
override __default_WARNFLAGS = -Wall -Wextra -Wpedantic

$(call arg_var,ARCH,native)
$(call arg_var,CC,gcc)
$(call arg_var,CPPFLAGS)
$(call arg_var,CPU)
$(call arg_var,CXX,g++)
$(call arg_var,TUNE,native)
$(call arg_var,WARNFLAGS)

$(call arg_bool_var,NO_COLOR)
$(call arg_bool_var,USE_CLANG)

$(call import-macros, \
cc-id-macros, \
cc, $(CC) -E -xc, \
__GNUC__ \
__GNUC_MINOR__ \
__GNUC_PATCHLEVEL__ \
Expand All @@ -26,35 +37,106 @@ $(call import-macros, \
$(.elif) __GNUC__ > 8 \
$.override __default_CSTD:=gnu2x \
$(.endif))
$(call arg_var,CSTD)

__clang__ = $(eval override $(if $(__clang_major__),__clang__:=1,undefine __clang__))$(__clang__)
cc_major = $(eval override cc_major := $$(or $$(__clang_major__),$$(__GNUC__)))$(cc_major)
cc_minor = $(eval override cc_minor := $$(or $$(__clang_minor__),$$(__GNUC_MINOR__)))$(cc_minor)
cc_patch = $(eval override cc_patch := $$(or $$(__clang_patchlevel__),$$(__GNUC_PATCHLEVEL__)))$(cc_patch)
cc_kind = $(eval override cc_kind := $$(if $$(__clang__),Clang,GCC))$(cc_kind)
cc_id = $(eval override cc_id := $$(cc_kind) $$(cc_major).$$(cc_minor).$$(cc_patch))$(cc_id)
override __default_USE_CCLANG = $(or $(USE_CLANG),$(if $(cc__clang_major__),1))
$(call arg_bool_var,USE_CCLANG)
$(if $(DEBUG_MK),$(info USE_CCLANG="$(USE_CCLANG)"))

override __default_CFLAGS = $(if $(ARCH),-march=$(ARCH)) \
$(if $(CPU),-mcpu=$(CPU)) $(if $(TUNE),-mtune=$(TUNE)) \
-O$(if $(DEBUG),$(if $(USE_CLANG),0,g) -ggdb3,2) -pipe \
-flto=$(if $(USE_CLANG),full,auto)
override __default_CWARNFLAGS = \
$(if $(USE_CCLANG), \
-Weverything \
$(addprefix -Wno-, \
c++98-compat \
c++98-compat-pedantic \
declaration-after-statement \
disabled-macro-expansion \
pre-c11-compat \
pre-c23-compat \
pre-c2x-compat \
unknown-warning-option \
unsafe-buffer-usage \
))
$(call arg_var,CWARNFLAGS)

override __default_CPPFLAGS = $(if $(DEBUG),,-DNDEBUG)
override __default_CXXFLAGS = $(__default_CFLAGS)
override __default_USE_CLANG = $(__clang__)
$(call import-macros, \
cxx, $(CXX) -E -xc++, \
__GNUC__ \
__GNUC_MINOR__ \
__GNUC_PATCHLEVEL__ \
__clang_major__ \
__clang_minor__ \
__clang_patchlevel__, \
__default_CXXSTD, \
$(.ifdef) __clang_major__ \
$(.if) __clang_major__ > 16 \
$.override __default_CXXSTD:=gnu++23 \
$(.elif) __clang_major__ > 11 \
$.override __default_CXXSTD:=gnu++2b \
$(.elif) __clang_major__ > 9 \
$.override __default_CXXSTD:=gnu++20 \
$(.elif) __clang_major__ > 4 \
$.override __default_CXXSTD:=gnu++2a \
$(.endif) \
$(.elif) __GNUC__ > 10 \
$.override __default_CXXSTD:=gnu++23 \
$(.elif) __GNUC__ > 9 \
$.override __default_CXXSTD:=gnu++20 \
$(.elif) __GNUC__ > 7 \
$.override __default_CXXSTD:=gnu++2a \
$(.endif))
$(call arg_var,CXXSTD)

$(call arg_var,CPU)
$(call arg_var,ARCH,native)
$(call arg_var,TUNE,native)
$(call arg_var,CSTD)
$(call arg_var,CXXSTD,gnu++23)
$(call arg_var,USE_CLANG)
override __default_USE_CXXCLANG = $(or $(USE_CLANG),$(if $(cxx__clang_major__),1))
$(call arg_bool_var,USE_CXXCLANG)
$(if $(DEBUG_MK),$(info USE_CXXCLANG="$(USE_CXXCLANG)"))

override __default_CXXWARNFLAGS = \
$(if $(USE_CXXCLANG), \
-Weverything \
$(addprefix -Wno-, \
c++98-compat \
c++98-compat-pedantic \
declaration-after-statement \
disabled-macro-expansion \
pre-c11-compat \
pre-c23-compat \
pre-c2x-compat \
unknown-warning-option \
unsafe-buffer-usage \
))
$(call arg_var,CXXWARNFLAGS)

override __default_NO_LTO = $(filter-out 11,$(USE_CCLANG)$(USE_CXXCLANG))
$(call arg_bool_var,NO_LTO)
$(if $(DEBUG_MK),$(info NO_LTO="$(NO_LTO)"))

override __default_CFLAGS = $(if $(ARCH),-march=$(ARCH)) $(if $(CPU),-mcpu=$(CPU)) \
$(if $(TUNE),-mtune=$(TUNE)) -O$(if $(DEBUG),$(if $(USE_CCLANG),0,g) -ggdb3,2) \
$(if $(NO_COLOR),,$(if $(USE_CCLANG),-fcolor-diagnostics)) \
$(if $(NO_LTO),,-flto=$(if $(USE_CCLANG),full,auto)) -pipe
$(call arg_var,CFLAGS)
$(call arg_var,CPPFLAGS)

override __default_CXXFLAGS = $(if $(ARCH),-march=$(ARCH)) $(if $(CPU),-mcpu=$(CPU)) \
$(if $(TUNE),-mtune=$(TUNE)) -O$(if $(DEBUG),$(if $(USE_CXXCLANG),0,g) -ggdb3,2) \
$(if $(NO_COLOR),,$(if $(USE_CXXLANG),-fcolor-diagnostics)) \
$(if $(NO_LTO),,-flto=$(if $(USE_CXXLANG),full,auto)) -pipe
$(call arg_var,CXXFLAGS)
$(call arg_var,WARNFLAGS,-Wall -Wextra -pedantic)

override C_BUILDFLAGS = -std=$(CSTD) $(CFLAGS) $(CPPFLAGS) $(WARNFLAGS)
override CXX_BUILDFLAGS = -std=$(CXXSTD) $(CXXFLAGS) $(CPPFLAGS) $(WARNFLAGS)
override C_BUILDFLAGS = $(eval \
override C_BUILDFLAGS := $$(strip $$(call pfx-if,-std=,$$(CSTD)) \
$$(CFLAGS) $$(CPPFLAGS) $$(WARNFLAGS) $$(CWARNFLAGS)))$(C_BUILDFLAGS)

override CXX_BUILDFLAGS = $(eval \
override CXX_BUILDFLAGS := $$(strip $$(call pfx-if,-std=,$$(CXXSTD)) \
$$(CXXFLAGS) $$(CPPFLAGS) $$(WARNFLAGS) $$(CXXWARNFLAGS)))$(CXX_BUILDFLAGS)

override cc_id = $(eval override cc_id := $$(strip $$(if $$(cc__clang_major__),\
clang $$(cc__clang_major__).$$(cc__clang_minor__).$$(cc__clang_patchlevel__),\
gcc $$(cc__GNUC__).$$(cc__GNUC_MINOR__).$$(cc__GNUC_PATCHLEVEL__))))$(cc_id)

override cxx_id = $(eval override cxx_id := $$(strip $$(if $$(cxx__clang_major__),\
clang++ $$(cxx__clang_major__).$$(cxx__clang_minor__).$$(cxx__clang_patchlevel__),\
g++ $$(cxx__GNUC__).$$(cxx__GNUC_MINOR__).$$(cxx__GNUC_PATCHLEVEL__))))$(cxx_id)

endif
102 changes: 68 additions & 34 deletions mk/internal.mk
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ else ifneq (undefined,$(origin DEBUG_MK))
override undefine DEBUG_MK
endif

override undefine w
override w := $w $w
override define n:=


endef

override . = $n
override .if = $.\#if
override .elif = $.\#elif
Expand All @@ -23,9 +24,23 @@ override .endif = $.\#endif

override pfx-if = $(if $2,$1$2)
override sfx-if = $(if $1,$1$2)
override join-2 = $2$(and $3,$2,$1)$3

# Read a command line variable with optional fallback.
override arg_var = $(call arg_var_,$(strip $(value 1)),$(strip $(value 2)))

override define arg_bool_var
$(call arg_var_,$(strip $(value 1)),$(strip $(value 2)))
$(eval
ifeq (command line,$$(origin $(strip $1)))
override $(strip $1):=$$(strip $$($(strip $1)))
ifneq (1,$$($(strip $1)))
override undefine $(strip $1)
endif
endif
)
endef

override define arg_var_
$(eval
ifeq (,$$(filter file override undefined,$$(firstword $$(origin __default_$1))))
Expand Down Expand Up @@ -120,70 +135,89 @@ override .get-macro-header = $(subst #,$n,$(shell $(or $2,$(CC) -E -xc) -w -P $1
sed 's/^ *//;s/ *$$//;/^$$/d;s/^override/#override/' | tail -c+2 | tr -d '\n'))

# $1: path of header file to create
# $2: list of preprocessor macro names to export as make variables
# $3: optional content to place above the generated export directives
# $2: optional name prefix for the exported make variables
# $3: list of preprocessor macro names to export as make variables
# $4: optional content to place above the generated export directives
override gen-guarded-macro-header = $(call .gen-macro-header \
,$(value 1),$(value 2),$(value 3),$(strip libcanth_$(shell \
,$(value 1),$(value 2),$(value 3),$(value 4),$(strip libcanth_$(shell \
echo '$(abspath $(strip $1))' | sha256sum | cut -c1-64)_))

# $1: path of header file to create
# $2: list of preprocessor macro names to export as make variables
# $3: optional content to place above the generated export directives
override gen-macro-header = $(call .gen-macro-header,$(value 1),$(value 2),$(value 3))
# $2: optional name prefix for the exported make variables
# $3: list of preprocessor macro names to export as make variables
# $4: optional content to place above the generated export directives
override gen-macro-header = $(call .gen-macro-header,$(value 1),$(value 2),$(value 3),$(value 4))

# Create a header file with export directives for preprocessor macros
# as make variables.
# $1: path of header file to create
# $2: list of preprocessor macro names to export as make variables
# $3: optional content to place above the generated export directives
# $4: optional header guard macro name
override .gen-macro-header = $(file >$1,$(if $(strip $4),#ifndef $4$n#define $4)$(if $(strip\
$(value 3)),$(value 3))$(foreach m,$2,$(call gen-macro-export,$m))$(if $(strip $4),$n#endif // $4))

override gen-macro-export = $n\#ifdef $1$n\#pragma push_macro("$1")$n\#undef $1$n\#define\
$1 override $1:=_Pragma("pop_macro(\"$1\")")$1$n$1$n\#else$noverride undefine $1$n\#endif
# $2: optional name prefix for the exported make variables
# $3: list of preprocessor macro names to export as make variables
# $4: optional content to place above the generated export directives
# $5: optional header guard macro name
override .gen-macro-header = $(file >$1,$(if $(strip $5),#ifndef $5$n#define $5)$(if $(strip \
$(value 4)),$(value 4))$(foreach m,$3,$(call gen-macro-export,$m,$(strip $2)))$(if $(strip \
$5),$n#endif // $5))

# Create a preprocessor directive to export a macro as a make variable.
# $1: preprocessor macro name
# $2: optional name prefix for the exported make variable
override gen-macro-export = $n\#ifdef $1$n\#pragma push_macro("$1")$n\#undef $1$n\#define $1\
override $2$1 := _Pragma("pop_macro(\"$1\")")$1$n$1$n\#else$noverride undefine $2$1$n\#endif

override define import-macros
$(foreach v,$2 $3,$(eval override $v = $$(.get-$O$(strip $1).h)$$($v)))
$(eval override .ext-$O$(strip $1).h := $$(value 4))
$(foreach v,$(3:%=$(strip $1)%) $4,$(eval override $v = $$(.get-$O$(strip $1).h)$$($v)))
$(eval override .ext-$O$(strip $1).h := $$(value 5))
$(eval override .get-$O$(strip $1).h = $$(eval \
$$(call gen-macro-header,$O$(strip $1).h,$2,$$(value .ext-$O$(strip $1).h)) \
$$(call get-macro-header,$O$(strip $1).h)override undefine .get-$O$(strip $1).h))
$$(call gen-macro-header,$O$(strip $1).h,$1,$3,$$(value .ext-$O$(strip $1).h)) \
$$(call get-macro-header,$O$(strip $1).h,$2)override undefine .get-$O$(strip $1).h))
endef

override about = $(if $(strip $2),$(call .about,$(call join-2, / ,$(if \
$(strip $(CC_OBJ_$(strip $1))),$(strip $(cc_id))),$(if \
$(strip $(CXX_OBJ_$(strip $1))),$(strip $(cxx_id))))))

# Generate rules and dependencies.
override define target_rules
$(eval override .O = $$(eval override .O :=$$$$(shell bash -c ' \
a=$$$$$$$$(realpath "$$$$O"); \
b=$$$$$$$$(realpath --relative-to="$$$$(THIS_DIR)" "$$$$O"); \
$(eval override .O=$$(eval override .O:=$$$$(shell bash -c 'a="$$$$O"; \
b=$$$$$$$$(realpath --relative-to="$$$$(THIS_DIR)" "$$$$$$$$a"); \
(( $$$$$$$${#a} > $$$$$$$${#b} )) || b="$$$$$$$${a%/}"; printf "%s/" \
"$$$$$$$$b"'))$$(if $$(.O:./=),,$$(eval override .O:=))$$(.O))
$(eval override undefine OBJ)
$(foreach t,$1,$(eval $t:| $$O$t) \
"$$$$$$$$b"'))$$(if $$(.O:./=),,$$(eval override .O:=))$$(.O)$n \
override undefine OBJ \
)$(foreach t,$1,$(eval $t:| $$O$t) \
$(eval override OBJ_$t := $$(SRC_$t:%=$$O%.o)) \
$(eval override DEP_$t := $$(OBJ_$t:%.o=%.d)) \
$(eval override CC_OBJ_$t := $$(OBJ_$t:%.cpp.o=)) \
$(eval override CXX_OBJ_$t := $$(OBJ_$t:%.c.o=)) \
$(eval $$(foreach s,$$(SRC_$t), \
$$(eval $$O$$s.o: $$(THIS_DIR)$$s))) \
$(if $(CXX_OBJ_$t), \
$(eval $$O$t: $$(OBJ_$t); $$(call msg,LINK,$$(.O)$t) \
+$Q$$(CXX) $$(CXX_BUILDFLAGS) -o $$@ $$^ $$(LIBS_$t)) \
$(eval $$(CXX_OBJ_$t):; $$(call msg,COMPILE,$$(@:$$O%=$$(.O)%)) \
$(eval $$O$t: $$(OBJ_$t); \
$$(call about,$t,$$?) \
$$(call msg,LINK,$$(.O)$t) \
+$Q$$(CXX) $$(CXX_BUILDFLAGS) -o $$@ $$^ $$(LIBS_$t)$n \
$$(CXX_OBJ_$t):; \
$$(call about,$t,$$?) \
$$(call msg,CXX,$$(@:$$O%=$$(.O)%)) \
+$Q$$(CXX) $$(CXX_BUILDFLAGS) -o $$@ -c -MMD $$<), \
$(eval $$O$t: $$(OBJ_$t); $$(call msg,LINK,$$(.O)$t) \
$(eval $$O$t: $$(OBJ_$t); \
$$(call about,$t,$$?) $$(call msg,LINK,$$(.O)$t) \
+$Q$$(CC) $$(C_BUILDFLAGS) -o $$@ $$^ $$(LIBS_$t))) \
$(if $(CC_OBJ_$t), \
$(eval $$(CC_OBJ_$t):; $$(call msg,COMPILE,$$(@:$$O%=$$(.O)%)) \
$(eval $$(CC_OBJ_$t):; \
$$(call about,$t,$$?) \
$$(call msg,CC,$$(@:$$O%=$$(.O)%)) \
+$Q$$(CC) $$(C_BUILDFLAGS) -o $$@ -c -MMD $$<)) \
$(eval clean-$t: $$(eval override WHAT_$t := \
$$$$(wildcard $$O$t $$(OBJ_$t) $$(DEP_$t)))) \
$(eval clean-$t: $$(if $$(WHAT_$t),| yeet);$$(if $$(WHAT_$t), \
$$(call msg,CLEAN,$$(.O)$t)$Q$$(RM) $$(WHAT_$t),$(nop))) \
$(eval install-$t:; $$(call msg,INSTALL,$$(.O)$t)$(nop)) \
$(eval override OBJ += $$(OBJ_$t)) \
)
$(eval override OBJ := $$(sort $$(OBJ)) \
$noverride DEP := $$(OBJ:%.o=%.d) \
$n-include $$(DEP) \
)$(eval \
override OBJ := $$(sort $$(OBJ))$n \
override DEP := $$(OBJ:.o=.d)$n \
-include $$(DEP) \
)
endef

Expand Down
Loading

0 comments on commit 2b3c3a2

Please sign in to comment.