diff --git a/eap_example/Makefile b/eap_example/Makefile
index 0cc19bd5359f..e5f3b3471035 100644
--- a/eap_example/Makefile
+++ b/eap_example/Makefile
@@ -1,19 +1,6 @@
 ALL=eap_example
 
-all: $(ALL)
-
-ifndef CC
-CC=gcc
-endif
-
-ifndef RANLIB
-RANLIB=ranlib
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
-
+include ../src/build.rules
 
 CFLAGS += -I.
 CFLAGS += -I../src
@@ -95,22 +82,6 @@ OBJS_server += ../src/eap_server/eap_server_tls_common.o
 CFLAGS += -DEAP_SERVER
 
 
-ifndef LDO
-LDO=$(CC)
-endif
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-
-%.o: %.c
-	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
-	@$(E) "  CC " $<
-
-
 OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server)
 
 OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 1400002a99a5..5c830fb448b1 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -1,10 +1,7 @@
-ifndef CC
-CC=gcc
-endif
+ALL=hostapd hostapd_cli
+VERIFY=verify_config
 
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../src/build.rules
 
 ifdef LIBS
 # If LIBS is set with some global build system defaults, clone those for
@@ -1264,31 +1261,6 @@ ifdef CONFIG_NO_TKIP
 CFLAGS += -DCONFIG_NO_TKIP
 endif
 
-ALL=hostapd hostapd_cli
-
-all: verify_config $(ALL)
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-ifeq ($(QUIET), 1)
-Q=@
-E=true
-endif
-
-ifdef CONFIG_CODE_COVERAGE
-%.o: %.c
-	@$(E) "  CC " $<
-	$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
-else
-%.o: %.c
-	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
-	@$(E) "  CC " $<
-endif
-
 verify_config:
 	@if [ ! -r .config ]; then \
 		echo 'Building hostapd requires a configuration file'; \
diff --git a/hs20/client/Makefile b/hs20/client/Makefile
index cc2af03f43f6..70fb73598dfe 100644
--- a/hs20/client/Makefile
+++ b/hs20/client/Makefile
@@ -1,28 +1,6 @@
-all: hs20-osu-client
+ALL=hs20-osu-client
 
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifeq ($(QUIET), 1)
-Q=@
-E=true
-else
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../../src/build.rules
 
 CFLAGS += -I../../src/utils
 CFLAGS += -I../../src/common
@@ -97,10 +75,6 @@ hs20-osu-client: $(OBJS)
 	$(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS)
 	@$(E) "  LD " $@
 
-%.o: %.c
-	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
-	@$(E) "  CC " $<
-
 clean:
 	rm -f core *~ *.o *.d hs20-osu-client
 	rm -f ../../src/utils/*.o
diff --git a/hs20/server/Makefile b/hs20/server/Makefile
index 9b7372796028..9ec7e4491ad4 100644
--- a/hs20/server/Makefile
+++ b/hs20/server/Makefile
@@ -1,16 +1,6 @@
-all: hs20_spp_server
+ALL=hs20_spp_server
 
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../../src/build.rules
 
 CFLAGS += -I../../src
 CFLAGS += -I../../src/utils
diff --git a/radius_example/Makefile b/radius_example/Makefile
index 883e2f2da577..75cb3caeb3dd 100644
--- a/radius_example/Makefile
+++ b/radius_example/Makefile
@@ -1,18 +1,6 @@
 ALL=radius_example
 
-all: $(ALL)
-
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
+include ../src/build.rules
 
 CFLAGS += -I.
 CFLAGS += -I../src
diff --git a/src/build.rules b/src/build.rules
new file mode 100644
index 000000000000..c83683ce6213
--- /dev/null
+++ b/src/build.rules
@@ -0,0 +1,42 @@
+all: $(VERIFY) $(ALL) $(EXTRA_TARGETS)
+
+ifndef CC
+CC=gcc
+endif
+
+ifndef RANLIB
+RANLIB=ranlib
+endif
+
+ifndef LDO
+LDO=$(CC)
+endif
+
+ifndef CFLAGS
+CFLAGS = -MMD -O2 -Wall -g
+endif
+
+Q=@
+E=echo
+ifeq ($(V), 1)
+Q=
+E=true
+endif
+ifeq ($(QUIET), 1)
+Q=@
+E=true
+endif
+
+ifeq ($(Q),@)
+MAKEFLAGS += --no-print-directory
+endif
+
+ifdef CONFIG_CODE_COVERAGE
+%.o: %.c
+	@$(E) "  CC " $<
+	$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
+else
+%.o: %.c
+	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
+	@$(E) "  CC " $<
+endif
diff --git a/tests/Makefile b/tests/Makefile
index 0817c9a27995..119ed7a2ae90 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,9 +1,9 @@
-TESTS=test-base64 test-md4 test-milenage \
+ALL=test-base64 test-md4 test-milenage \
 	test-rsa-sig-ver \
 	test-sha1 \
 	test-sha256 test-aes test-asn1 test-x509v3 test-list test-rc4
 
-all: $(TESTS)
+include ../src/build.rules
 
 ifdef LIBFUZZER
 CC=clang
@@ -14,18 +14,6 @@ LDFLAGS += -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-ov
 TEST_FUZZ=y
 endif
 
-ifndef CC
-CC=gcc
-endif
-
-ifndef LDO
-LDO=$(CC)
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
-
 ifdef TEST_FUZZ
 CFLAGS += -DCONFIG_NO_RANDOM_POOL
 CFLAGS += -DTEST_FUZZ
@@ -152,7 +140,7 @@ test-x509v3: test-x509v3.o $(LIBS)
 	$(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
 
 
-run-tests: $(TESTS)
+run-tests: $(ALL)
 	./test-aes
 	./test-list
 	./test-md4
@@ -165,7 +153,7 @@ run-tests: $(TESTS)
 
 clean:
 	$(MAKE) -C ../src clean
-	rm -f $(TESTS) *~ *.o *.d
+	rm -f $(ALL) *~ *.o *.d
 	rm -f test-eapol
 	rm -f test-https
 	rm -f test-json
diff --git a/wlantest/Makefile b/wlantest/Makefile
index 22ea646c0926..0324fa54855e 100644
--- a/wlantest/Makefile
+++ b/wlantest/Makefile
@@ -1,22 +1,9 @@
 ALL=wlantest wlantest_cli test_vectors
 
-all: $(ALL)
+include ../src/build.rules
 
 UNAME := $(shell uname -s)
 
-ifndef CC
-CC=gcc
-endif
-
-ifndef RANLIB
-RANLIB=ranlib
-endif
-
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
-endif
-
-
 CFLAGS += -I.
 CFLAGS += -I../src
 CFLAGS += -I../src/utils
@@ -26,26 +13,6 @@ ifneq ($(UNAME),Darwin)
 LIBS += -lrt
 endif
 
-ifndef LDO
-LDO=$(CC)
-endif
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-ifeq ($(QUIET), 1)
-Q=@
-E=true
-endif
-
-%.o: %.c
-	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
-	@$(E) "  CC " $<
-
-
 OWN_LIBS += ../src/utils/libutils.a
 OWN_LIBS += ../src/crypto/libcrypto.a
 
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index a01a32982dfe..13d938168758 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -1,11 +1,24 @@
-ifndef CC
-CC=gcc
+BINALL=wpa_supplicant wpa_cli
+
+ifndef CONFIG_NO_WPA_PASSPHRASE
+BINALL += wpa_passphrase
 endif
 
-ifndef CFLAGS
-CFLAGS = -MMD -O2 -Wall -g
+ALL = $(BINALL)
+ALL += systemd/wpa_supplicant.service
+ALL += systemd/wpa_supplicant@.service
+ALL += systemd/wpa_supplicant-nl80211@.service
+ALL += systemd/wpa_supplicant-wired@.service
+ALL += dbus/fi.w1.wpa_supplicant1.service
+ifdef CONFIG_BUILD_WPA_CLIENT_SO
+ALL += libwpa_client.so
 endif
 
+VERIFY=verify_config
+EXTRA_TARGETS=dynamic_eap_methods
+
+include ../src/build.rules
+
 ifdef LIBS
 # If LIBS is set with some global build system defaults, clone those for
 # LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well.
@@ -44,25 +57,6 @@ CONFIG_WPS_TESTING=y
 CONFIG_TDLS_TESTING=y
 endif
 
-BINALL=wpa_supplicant wpa_cli
-
-ifndef CONFIG_NO_WPA_PASSPHRASE
-BINALL += wpa_passphrase
-endif
-
-ALL = $(BINALL)
-ALL += systemd/wpa_supplicant.service
-ALL += systemd/wpa_supplicant@.service
-ALL += systemd/wpa_supplicant-nl80211@.service
-ALL += systemd/wpa_supplicant-wired@.service
-ALL += dbus/fi.w1.wpa_supplicant1.service
-ifdef CONFIG_BUILD_WPA_CLIENT_SO
-ALL += libwpa_client.so
-endif
-
-
-all: verify_config $(ALL) dynamic_eap_methods
-
 verify_config:
 	@if [ ! -r .config ]; then \
 		echo 'Building wpa_supplicant requires a configuration file'; \
@@ -1867,21 +1861,6 @@ ifdef CONFIG_NO_TKIP
 CFLAGS += -DCONFIG_NO_TKIP
 endif
 
-ifndef LDO
-LDO=$(CC)
-endif
-
-Q=@
-E=echo
-ifeq ($(V), 1)
-Q=
-E=true
-endif
-ifeq ($(QUIET), 1)
-Q=@
-E=true
-endif
-
 dynamic_eap_methods: $(EAPDYN)
 
 ../src/drivers/build.wpa_supplicant:
@@ -1980,16 +1959,6 @@ eap_eke.so: ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c
 	$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \
 		-D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init
 
-ifdef CONFIG_CODE_COVERAGE
-%.o: %.c
-	@$(E) "  CC " $<
-	$(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<)
-else
-%.o: %.c
-	$(Q)$(CC) -c -o $@ $(CFLAGS) $<
-	@$(E) "  CC " $<
-endif
-
 %.service: %.service.in
 	$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
 	@$(E) "  sed" $<
