xref: /freebsd/contrib/bmake/mk/warnings.mk (revision bdd1243d)
1# RCSid:
2#	$Id: warnings.mk,v 1.17 2023/02/16 17:55:52 sjg Exp $
3#
4#	@(#) Copyright (c) 2002-2023, Simon J. Gerraty
5#
6#	This file is provided in the hope that it will
7#	be of use.  There is absolutely NO WARRANTY.
8#	Permission to copy, redistribute or otherwise
9#	use this file is hereby granted provided that
10#	the above copyright notice and this notice are
11#	left intact.
12#
13#	Please send copies of changes and bug-fixes to:
14#	sjg@crufty.net
15#
16
17.ifndef _w_cflags
18# make sure we get the behavior we expect
19.MAKE.SAVE_DOLLARS = no
20
21# Any number of warnings sets can be added.
22.-include <warnings-sets.mk>
23# This is more in keeping with our current practice
24.-include <local.warnings.mk>
25
26# Modest defaults - put more elaborate sets in warnings-sets.mk
27# -Wunused  etc are here so you can set
28# W_unused=-Wno-unused etc.
29MIN_WARNINGS ?= -Wall \
30	-Wformat \
31	-Wimplicit \
32	-Wunused \
33	-Wuninitialized
34
35LOW_WARNINGS ?= ${MIN_WARNINGS} -W -Wstrict-prototypes -Wmissing-prototypes
36
37MEDIUM_WARNINGS ?= ${LOW_WARNINGS}
38
39HIGH_WARNINGS ?= ${MEDIUM_WARNINGS} \
40	-Wcast-align \
41	-Wcast-qual \
42	-Wparentheses \
43	-Wpointer-arith \
44	-Wmissing-declarations \
45	-Wreturn-type \
46	-Wswitch \
47	-Wwrite-strings
48
49EXTRA_WARNINGS ?= ${HIGH_WARNINGS} -Wextra
50
51# The two step default makes it easier to test build with different defaults.
52DEFAULT_WARNINGS_SET ?= MIN
53WARNINGS_SET ?= ${DEFAULT_WARNINGS_SET}
54
55# There is always someone who wants more...
56.if !empty(WARNINGS_XTRAS)
57${WARNINGS_SET}_WARNINGS += ${WARNINGS_XTRAS}
58.endif
59
60# Keep this list ordered!
61WARNINGS_SET_LIST ?= MIN LOW MEDIUM HIGH EXTRA
62
63# We assume WARNINGS_SET_LIST is an ordered list.
64# if WARNINGS_SET is < WERROR_SET we add WARNINGS_NO_ERROR
65# otherwise we add WARNINGS_ERROR
66DEFAULT_WERROR_SET ?= MEDIUM
67WERROR_SET ?= ${DEFAULT_WERROR_SET}
68WARNINGS_ERROR ?= -Werror
69WARNINGS_NO_ERROR ?=
70
71.if ${MAKE_VERSION} >= 20170130
72.for i in ${WARNINGS_SET_LIST:range}
73.if ${WARNINGS_SET_LIST:[$i]} == ${WARNINGS_SET}
74WARNINGS_SETx = $i
75.endif
76.if ${WARNINGS_SET_LIST:[$i]} == ${WERROR_SET}
77WERROR_SETx = $i
78.if ${MAKE_VERSION} >= 20220924
79.break
80.endif
81.endif
82.endfor
83.if ${WARNINGS_SETx:U${WERROR_SETx:U0}} < ${WERROR_SETx:U0}
84${WARNINGS_SET}_WARNINGS += ${WARNINGS_NO_ERROR:U}
85.else
86${WARNINGS_SET}_WARNINGS += ${WARNINGS_ERROR}
87.endif
88.endif
89
90.if !empty(WARNINGS_SET)
91.for ws in ${WARNINGS_SET}
92.if empty(${ws}_WARNINGS)
93.if ${MAKE_VERSION:[1]:C/.*-//} >= 20050530
94.BEGIN:	_empty_warnings
95_empty_warnings: .PHONY
96.else
97.BEGIN:
98.endif
99	@echo "ERROR: Invalid: WARNINGS_SET=${ws}"
100	@echo "ERROR: Try one of: ${WARNINGS_SET_LIST}"; exit 1
101
102.endif
103.endfor
104.endif
105
106# Without -O or if we've set -O0 somewhere - to make debugging more effective,
107# we need to turn off -Wuninitialized as otherwise we get a warning that
108# -Werror turns into an error.  To be safe, set W_uninitialized blank.
109_w_cflags= ${CFLAGS} ${CFLAGS_LAST} ${CPPFLAGS}
110.if ${_w_cflags:M-O*} == "" || ${_w_cflags:M-O0} != ""
111W_uninitialized=
112.endif
113
114
115# .for loops have the [dis]advantage of being evaluated when read,
116# so adding to WARNINGS_SET[_${MACHINE_ARCH}] after this file is
117# read has no effect.
118# Replacing the above .for loops with the WARNINGS+= below solves that
119# but tiggers a double free bug in bmake-20040118 and earlier.
120# Don't try and read this too fast!
121#
122# The first :@ "loop" handles multiple sets in WARNINGS_SET
123#
124# In the second :@ "loop", the ::?= noise sets W_foo?=-Wfoo etc
125# which makes it easy to turn off override individual flags
126# (see W_uninitialized above).
127#
128# The last bit expands to
129# ${W_foo_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}:U${W_foo}}
130# which is the bit we ultimately want.  It allows W_* to be set on a
131# per target basis.
132#
133# NOTE: that we force the target extension to be .o
134# TARGET_PREFIX_FILTER defaults to R
135#
136
137TARGET_PREFIX_FILTER ?= R
138
139# define this once, we use it a couple of times below (hence the doubled $$).
140M_warnings_list = @s@$${$$s_WARNINGS} $${$$s_WARNINGS.${COMPILER_TYPE}:U}@:O:u:@w@$${$${w:C/-(.)/\1_/}::?=$$w} $${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U$${$${w:C/-(.)/\1_/}_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U$${$${w:C/-(.)/\1_/}_${MACHINE_ARCH}:U$${$${w:C/-(.)/\1_/}}}}}@
141
142# first a list of warnings from the chosen set
143_warnings = ${WARNINGS_SET_${MACHINE_ARCH}:U${WARNINGS_SET}:${M_warnings_list}}
144# now a list of all -Wno-* overrides not just those defined by WARNINGS_SET
145# since things like -Wall imply lots of others.
146# this should be a super-set of the -Wno-* in _warnings, but
147# just in case...
148_no_warnings = ${_warnings:M-Wno-*} ${WARNINGS_SET_LIST:${M_warnings_list}:M-Wno-*}
149# -Wno-* must follow any others
150WARNINGS += ${_warnings:N-Wno-*} ${_no_warnings:O:u}
151
152.ifndef NO_CFLAGS_WARNINGS
153# Just ${WARNINGS} should do, but this is more flexible?
154CFLAGS+= ${WARNINGS_${.TARGET:T:${TARGET_PREFIX_FILTER:ts:}}.o:U${WARNINGS}}
155.endif
156
157# it is rather silly that g++ blows up on some warning flags
158NO_CXX_WARNINGS+= \
159	implicit \
160	missing-declarations \
161	missing-prototypes \
162	nested-externs \
163	shadow \
164	strict-prototypes
165
166WARNINGS_CXX_SRCS += ${SRCS:M*.c*:N*.c:N*h}
167.for s in ${WARNINGS_CXX_SRCS:O:u}
168.for w in ${NO_CXX_WARNINGS}
169W_$w_${s:T:${TARGET_PREFIX_FILTER:ts:}}.o=
170.endfor
171.endfor
172
173.endif # _w_cflags
174