1296124Sbdrewery# $FreeBSD: stable/11/share/mk/bsd.clang-analyze.mk 360660 2020-05-05 17:10:49Z dim $
2296124Sbdrewery#
3296124Sbdrewery# Support Clang static analyzer on SRCS.
4296124Sbdrewery#
5296124Sbdrewery#
6296124Sbdrewery# +++ variables +++
7296124Sbdrewery#
8296124Sbdrewery# CLANG_ANALYZE_CHECKERS	Which checkers to run for all sources.
9296124Sbdrewery#
10296124Sbdrewery# CLANG_ANALYZE_CXX_CHECKERS	Which checkers to run for C++ sources.
11296124Sbdrewery#
12296124Sbdrewery# CLANG_ANALYZE_OUTPUT		Output format for generated files.
13296124Sbdrewery# 				text - don't generate extra files.
14296124Sbdrewery# 				html - generate html in obj.plist/ directories.
15296124Sbdrewery# 				plist - generate xml obj.plist files.
16296124Sbdrewery# 				See also:
17360660Sdim# 				  contrib/llvm-project/clang/include/clang/StaticAnalyzer/Core/Analyses.def
18296124Sbdrewery#
19296124Sbdrewery# CLANG_ANALYZE_OUTPUT_DIR	Sets which directory output set by
20296124Sbdrewery# 				CLANG_ANALYZE_OUTPUT is placed into.
21296124Sbdrewery#
22296124Sbdrewery# +++ targets +++
23296124Sbdrewery#
24296124Sbdrewery#	analyze:
25296124Sbdrewery#		Run the Clang static analyzer against all sources and present
26296124Sbdrewery#		output on stdout.
27296124Sbdrewery
28296124Sbdrewery.if !target(__<bsd.clang-analyze.mk>__)
29296124Sbdrewery__<bsd.clang-analyze.mk>__:
30296124Sbdrewery
31296124Sbdrewery.include <bsd.compiler.mk>
32296124Sbdrewery
33296124Sbdrewery.if ${COMPILER_TYPE} != "clang" && (make(analyze) || make(*.clang-analyzer))
34296124Sbdrewery.error Clang static analyzer requires clang but found that compiler '${CC}' is ${COMPILER_TYPE}
35296124Sbdrewery.endif
36296124Sbdrewery
37296124SbdreweryCLANG_ANALYZE_OUTPUT?=	text
38296124SbdreweryCLANG_ANALYZE_OUTPUT_DIR?=	clang-analyze
39296124SbdreweryCLANG_ANALYZE_FLAGS+=	--analyze \
40296124Sbdrewery			-Xanalyzer -analyzer-output=${CLANG_ANALYZE_OUTPUT} \
41296124Sbdrewery			-o ${CLANG_ANALYZE_OUTPUT_DIR}
42296124Sbdrewery
43296124SbdreweryCLANG_ANALYZE_CHECKERS+=	core deadcode security unix
44296124SbdreweryCLANG_ANALYZE_CXX_CHECKERS+=	cplusplus
45296124Sbdrewery
46296124Sbdrewery.for checker in ${CLANG_ANALYZE_CHECKERS}
47296124SbdreweryCLANG_ANALYZE_FLAGS+=	-Xanalyzer -analyzer-checker=${checker}
48296124Sbdrewery.endfor
49296124SbdreweryCLANG_ANALYZE_CXX_FLAGS+=	${CLANG_ANALYZE_FLAGS}
50296124Sbdrewery.for checker in ${CLANG_ANALYZE_CXX_CHECKERS}
51296124SbdreweryCLANG_ANALYZE_CXX_FLAGS+=	-Xanalyzer -analyzer-checker=${checker}
52296124Sbdrewery.endfor
53296124Sbdrewery
54296124Sbdrewery.SUFFIXES: .c .cc .cpp .cxx .C .clang-analyzer
55296124Sbdrewery
56296124SbdreweryCLANG_ANALYZE_CFLAGS=	${CFLAGS:N-Wa,--fatal-warnings}
57296124SbdreweryCLANG_ANALYZE_CXXFLAGS=	${CXXFLAGS:N-Wa,--fatal-warnings}
58296124Sbdrewery
59296124Sbdrewery.c.clang-analyzer:
60296124Sbdrewery	${CC:N${CCACHE_BIN}} ${CLANG_ANALYZE_FLAGS} \
61297282Sbdrewery	    ${CLANG_ANALYZE_CFLAGS} \
62297282Sbdrewery	    ${.IMPSRC}
63296124Sbdrewery.cc.clang-analyzer .cpp.clang-analyzer .cxx.clang-analyzer .C.clang-analyzer:
64296124Sbdrewery	${CXX:N${CCACHE_BIN}} ${CLANG_ANALYZE_CXX_FLAGS} \
65297282Sbdrewery	    ${CLANG_ANALYZE_CXXFLAGS} \
66297282Sbdrewery	    ${.IMPSRC}
67296124Sbdrewery
68296124SbdreweryCLANG_ANALYZE_SRCS= \
69296124Sbdrewery	${SRCS:M*.[cC]} ${SRCS:M*.cc} \
70296124Sbdrewery	${SRCS:M*.cpp} ${SRCS:M*.cxx} \
71296124Sbdrewery	${DPSRCS:M*.[cC]} ${DPSRCS:M*.cc} \
72296124Sbdrewery	${DPSRCS:M*.cpp} ${DPSRCS:M*.cxx}
73296124Sbdrewery.if !empty(CLANG_ANALYZE_SRCS)
74296124SbdreweryCLANG_ANALYZE_OBJS=	${CLANG_ANALYZE_SRCS:O:u:R:S,$,.clang-analyzer,}
75296124Sbdrewery.NOPATH:	${CLANG_ANALYZE_OBJS}
76296124Sbdrewery.endif
77296124Sbdrewery
78296124Sbdrewery# .depend files aren't relevant here since they reference obj.o rather than
79296124Sbdrewery# obj.clang-analyzer, so add in some guesses in case 'make depend' wasn't ran,
80296124Sbdrewery# for when directly building 'obj.clang-analyzer'.
81296124Sbdrewery.for __obj in ${CLANG_ANALYZE_OBJS}
82296124Sbdrewery${__obj}: ${OBJS_DEPEND_GUESS}
83296124Sbdrewery${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
84296124Sbdrewery.endfor
85296124Sbdrewery
86297434Sbdrewerybeforeanalyze: depend .PHONY
87296124Sbdrewery.if !defined(_RECURSING_PROGS) && !empty(CLANG_ANALYZE_SRCS) && \
88296124Sbdrewery    ${CLANG_ANALYZE_OUTPUT} != "text"
89296124Sbdrewery	mkdir -p ${CLANG_ANALYZE_OUTPUT_DIR}
90296124Sbdrewery.endif
91296124Sbdrewery
92296124Sbdrewery.if !target(analyze)
93296124Sbdreweryanalyze: beforeanalyze .WAIT ${CLANG_ANALYZE_OBJS}
94296124Sbdrewery.endif
95296124Sbdrewery
96296124Sbdrewery.if exists(${CLANG_ANALYZE_OUTPUT_DIR})
97296124SbdreweryCLEANDIRS+=	${CLANG_ANALYZE_OUTPUT_DIR}
98296124Sbdrewery.endif
99296124Sbdrewery
100296124Sbdrewery.endif	# !target(__<bsd.clang-analyze.mk>__)
101