diff --git a/Makefile b/Makefile
index c55b0acda7a723250db48f309357baee911fb032..5c60f893e33a43361bfd486c62660c94e172ccf8 100644
--- a/Makefile
+++ b/Makefile
@@ -229,11 +229,29 @@ prefix ?= /usr/local
 PROTOC ?= protoc
 DTRACE ?= dtrace
 CONFIG ?= opt
-CC ?= $(CC_$(CONFIG))
-CXX ?= $(CXX_$(CONFIG))
-LD ?= $(LD_$(CONFIG))
+# Doing X ?= Y is the same as:
+# ifeq ($(origin X), undefined)
+#  X = Y
+# endif
+# but some variables, such as CC, CXX, LD or AR, have defaults.
+# So instead of using ?= on them, we need to check their origin.
+# See:
+#  https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
+#  https://www.gnu.org/software/make/manual/html_node/Flavors.html#index-_003f_003d
+#  https://www.gnu.org/software/make/manual/html_node/Origin-Function.html
+ifeq ($(origin CC), default)
+CC = $(CC_$(CONFIG))
+endif
+ifeq ($(origin CXX), default)
+CXX = $(CXX_$(CONFIG))
+endif
+ifeq ($(origin LD), default)
+LD = $(LD_$(CONFIG))
+endif
 LDXX ?= $(LDXX_$(CONFIG))
-AR ?= ar
+ifeq ($(origin AR), default)
+AR = ar
+endif
 ifeq ($(SYSTEM),Linux)
 STRIP ?= strip --strip-unneeded
 else
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 351d5ecd0356ef55e1096b4869c63ec44f03e0e3..a4fcf667825213e46cc7a2919a6b1aa7c903cd23 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -133,11 +133,29 @@
   PROTOC ?= protoc
   DTRACE ?= dtrace
   CONFIG ?= opt
-  CC ?= $(CC_$(CONFIG))
-  CXX ?= $(CXX_$(CONFIG))
-  LD ?= $(LD_$(CONFIG))
+  # Doing X ?= Y is the same as:
+  # ifeq ($(origin X), undefined)
+  #  X = Y
+  # endif
+  # but some variables, such as CC, CXX, LD or AR, have defaults.
+  # So instead of using ?= on them, we need to check their origin.
+  # See:
+  #  https://www.gnu.org/software/make/manual/html_node/Implicit-Variables.html
+  #  https://www.gnu.org/software/make/manual/html_node/Flavors.html#index-_003f_003d
+  #  https://www.gnu.org/software/make/manual/html_node/Origin-Function.html
+  ifeq ($(origin CC), default)
+  CC = $(CC_$(CONFIG))
+  endif
+  ifeq ($(origin CXX), default)
+  CXX = $(CXX_$(CONFIG))
+  endif
+  ifeq ($(origin LD), default)
+  LD = $(LD_$(CONFIG))
+  endif
   LDXX ?= $(LDXX_$(CONFIG))
-  AR ?= ar
+  ifeq ($(origin AR), default)
+  AR = ar
+  endif
   ifeq ($(SYSTEM),Linux)
   STRIP ?= strip --strip-unneeded
   else