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