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