bsd.clang-analyze.mk revision 296124
1# $FreeBSD: head/share/mk/bsd.clang-analyze.mk 296124 2016-02-26 22:14:00Z bdrewery $
2#
3# Support Clang static analyzer on SRCS.
4#
5#
6# +++ variables +++
7#
8# CLANG_ANALYZE_CHECKERS	Which checkers to run for all sources.
9#
10# CLANG_ANALYZE_CXX_CHECKERS	Which checkers to run for C++ sources.
11#
12# CLANG_ANALYZE_OUTPUT		Output format for generated files.
13# 				text - don't generate extra files.
14# 				html - generate html in obj.plist/ directories.
15# 				plist - generate xml obj.plist files.
16# 				See also:
17# 				  contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def
18#
19# CLANG_ANALYZE_OUTPUT_DIR	Sets which directory output set by
20# 				CLANG_ANALYZE_OUTPUT is placed into.
21#
22# +++ targets +++
23#
24#	analyze:
25#		Run the Clang static analyzer against all sources and present
26#		output on stdout.
27
28.if !target(__<bsd.clang-analyze.mk>__)
29__<bsd.clang-analyze.mk>__:
30
31.include <bsd.compiler.mk>
32
33.if ${COMPILER_TYPE} != "clang" && (make(analyze) || make(*.clang-analyzer))
34.error Clang static analyzer requires clang but found that compiler '${CC}' is ${COMPILER_TYPE}
35.endif
36
37CLANG_ANALYZE_OUTPUT?=	text
38CLANG_ANALYZE_OUTPUT_DIR?=	clang-analyze
39CLANG_ANALYZE_FLAGS+=	--analyze \
40			-Xanalyzer -analyzer-output=${CLANG_ANALYZE_OUTPUT} \
41			-o ${CLANG_ANALYZE_OUTPUT_DIR}
42
43CLANG_ANALYZE_CHECKERS+=	core deadcode security unix
44CLANG_ANALYZE_CXX_CHECKERS+=	cplusplus
45
46.for checker in ${CLANG_ANALYZE_CHECKERS}
47CLANG_ANALYZE_FLAGS+=	-Xanalyzer -analyzer-checker=${checker}
48.endfor
49CLANG_ANALYZE_CXX_FLAGS+=	${CLANG_ANALYZE_FLAGS}
50.for checker in ${CLANG_ANALYZE_CXX_CHECKERS}
51CLANG_ANALYZE_CXX_FLAGS+=	-Xanalyzer -analyzer-checker=${checker}
52.endfor
53
54.SUFFIXES: .c .cc .cpp .cxx .C .clang-analyzer
55
56CLANG_ANALYZE_CFLAGS=	${CFLAGS:N-Wa,--fatal-warnings}
57CLANG_ANALYZE_CXXFLAGS=	${CXXFLAGS:N-Wa,--fatal-warnings}
58
59.c.clang-analyzer:
60	${CC:N${CCACHE_BIN}} ${CLANG_ANALYZE_FLAGS} \
61	    ${CLANG_ANALYZE_CFLAGS} ${CPPFLAGS} \
62	    ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \
63	    ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC}
64.cc.clang-analyzer .cpp.clang-analyzer .cxx.clang-analyzer .C.clang-analyzer:
65	${CXX:N${CCACHE_BIN}} ${CLANG_ANALYZE_CXX_FLAGS} \
66	    ${CLANG_ANALYZE_CXXFLAGS} ${CPPFLAGS} \
67	    ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \
68	    ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC}
69
70CLANG_ANALYZE_SRCS= \
71	${SRCS:M*.[cC]} ${SRCS:M*.cc} \
72	${SRCS:M*.cpp} ${SRCS:M*.cxx} \
73	${DPSRCS:M*.[cC]} ${DPSRCS:M*.cc} \
74	${DPSRCS:M*.cpp} ${DPSRCS:M*.cxx}
75.if !empty(CLANG_ANALYZE_SRCS)
76CLANG_ANALYZE_OBJS=	${CLANG_ANALYZE_SRCS:O:u:R:S,$,.clang-analyzer,}
77.NOPATH:	${CLANG_ANALYZE_OBJS}
78.endif
79
80# .depend files aren't relevant here since they reference obj.o rather than
81# obj.clang-analyzer, so add in some guesses in case 'make depend' wasn't ran,
82# for when directly building 'obj.clang-analyzer'.
83.for __obj in ${CLANG_ANALYZE_OBJS}
84${__obj}: ${OBJS_DEPEND_GUESS}
85${__obj}: ${OBJS_DEPEND_GUESS.${__obj}}
86.endfor
87
88.if ${MK_FAST_DEPEND} == "yes"
89beforeanalyze: depend
90.endif
91beforeanalyze: .PHONY
92.if !defined(_RECURSING_PROGS) && !empty(CLANG_ANALYZE_SRCS) && \
93    ${CLANG_ANALYZE_OUTPUT} != "text"
94	mkdir -p ${CLANG_ANALYZE_OUTPUT_DIR}
95.endif
96
97.if !target(analyze)
98analyze: beforeanalyze .WAIT ${CLANG_ANALYZE_OBJS}
99.endif
100
101.if exists(${CLANG_ANALYZE_OUTPUT_DIR})
102CLEANDIRS+=	${CLANG_ANALYZE_OUTPUT_DIR}
103.endif
104
105.endif	# !target(__<bsd.clang-analyze.mk>__)
106