Index: head/share/man/man7/build.7 =================================================================== --- head/share/man/man7/build.7 +++ head/share/man/man7/build.7 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd October 21, 2015 +.Dd February 26, 2016 .Dt BUILD 7 .Os .Sh NAME @@ -107,6 +107,8 @@ The following list provides the names and actions for the targets supported by the build system: .Bl -tag -width ".Cm cleandepend" +.It Cm analyze +Run Clang static analyzer against all objects and present output on stdout. .It Cm check Run tests for a given subdirectory. The default directory used is Index: head/share/mk/Makefile =================================================================== --- head/share/mk/Makefile +++ head/share/mk/Makefile @@ -17,6 +17,7 @@ auto.obj.mk \ bsd.README \ bsd.arch.inc.mk \ + bsd.clang-analyze.mk \ bsd.compiler.mk \ bsd.confs.mk \ bsd.cpu.mk \ Index: head/share/mk/bsd.clang-analyze.mk =================================================================== --- head/share/mk/bsd.clang-analyze.mk +++ head/share/mk/bsd.clang-analyze.mk @@ -0,0 +1,105 @@ +# $FreeBSD$ +# +# Support Clang static analyzer on SRCS. +# +# +# +++ variables +++ +# +# CLANG_ANALYZE_CHECKERS Which checkers to run for all sources. +# +# CLANG_ANALYZE_CXX_CHECKERS Which checkers to run for C++ sources. +# +# CLANG_ANALYZE_OUTPUT Output format for generated files. +# text - don't generate extra files. +# html - generate html in obj.plist/ directories. +# plist - generate xml obj.plist files. +# See also: +# contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Analyses.def +# +# CLANG_ANALYZE_OUTPUT_DIR Sets which directory output set by +# CLANG_ANALYZE_OUTPUT is placed into. +# +# +++ targets +++ +# +# analyze: +# Run the Clang static analyzer against all sources and present +# output on stdout. + +.if !target(____) +____: + +.include + +.if ${COMPILER_TYPE} != "clang" && (make(analyze) || make(*.clang-analyzer)) +.error Clang static analyzer requires clang but found that compiler '${CC}' is ${COMPILER_TYPE} +.endif + +CLANG_ANALYZE_OUTPUT?= text +CLANG_ANALYZE_OUTPUT_DIR?= clang-analyze +CLANG_ANALYZE_FLAGS+= --analyze \ + -Xanalyzer -analyzer-output=${CLANG_ANALYZE_OUTPUT} \ + -o ${CLANG_ANALYZE_OUTPUT_DIR} + +CLANG_ANALYZE_CHECKERS+= core deadcode security unix +CLANG_ANALYZE_CXX_CHECKERS+= cplusplus + +.for checker in ${CLANG_ANALYZE_CHECKERS} +CLANG_ANALYZE_FLAGS+= -Xanalyzer -analyzer-checker=${checker} +.endfor +CLANG_ANALYZE_CXX_FLAGS+= ${CLANG_ANALYZE_FLAGS} +.for checker in ${CLANG_ANALYZE_CXX_CHECKERS} +CLANG_ANALYZE_CXX_FLAGS+= -Xanalyzer -analyzer-checker=${checker} +.endfor + +.SUFFIXES: .c .cc .cpp .cxx .C .clang-analyzer + +CLANG_ANALYZE_CFLAGS= ${CFLAGS:N-Wa,--fatal-warnings} +CLANG_ANALYZE_CXXFLAGS= ${CXXFLAGS:N-Wa,--fatal-warnings} + +.c.clang-analyzer: + ${CC:N${CCACHE_BIN}} ${CLANG_ANALYZE_FLAGS} \ + ${CLANG_ANALYZE_CFLAGS} ${CPPFLAGS} \ + ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \ + ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC} +.cc.clang-analyzer .cpp.clang-analyzer .cxx.clang-analyzer .C.clang-analyzer: + ${CXX:N${CCACHE_BIN}} ${CLANG_ANALYZE_CXX_FLAGS} \ + ${CLANG_ANALYZE_CXXFLAGS} ${CPPFLAGS} \ + ${COPTS.${.IMPSRC:T}} ${CPUFLAGS.${.IMPSRC:T}} \ + ${CPPFLAGS.${.IMPSRC:T}} ${.IMPSRC} + +CLANG_ANALYZE_SRCS= \ + ${SRCS:M*.[cC]} ${SRCS:M*.cc} \ + ${SRCS:M*.cpp} ${SRCS:M*.cxx} \ + ${DPSRCS:M*.[cC]} ${DPSRCS:M*.cc} \ + ${DPSRCS:M*.cpp} ${DPSRCS:M*.cxx} +.if !empty(CLANG_ANALYZE_SRCS) +CLANG_ANALYZE_OBJS= ${CLANG_ANALYZE_SRCS:O:u:R:S,$,.clang-analyzer,} +.NOPATH: ${CLANG_ANALYZE_OBJS} +.endif + +# .depend files aren't relevant here since they reference obj.o rather than +# obj.clang-analyzer, so add in some guesses in case 'make depend' wasn't ran, +# for when directly building 'obj.clang-analyzer'. +.for __obj in ${CLANG_ANALYZE_OBJS} +${__obj}: ${OBJS_DEPEND_GUESS} +${__obj}: ${OBJS_DEPEND_GUESS.${__obj}} +.endfor + +.if ${MK_FAST_DEPEND} == "yes" +beforeanalyze: depend +.endif +beforeanalyze: .PHONY +.if !defined(_RECURSING_PROGS) && !empty(CLANG_ANALYZE_SRCS) && \ + ${CLANG_ANALYZE_OUTPUT} != "text" + mkdir -p ${CLANG_ANALYZE_OUTPUT_DIR} +.endif + +.if !target(analyze) +analyze: beforeanalyze .WAIT ${CLANG_ANALYZE_OBJS} +.endif + +.if exists(${CLANG_ANALYZE_OUTPUT_DIR}) +CLEANDIRS+= ${CLANG_ANALYZE_OUTPUT_DIR} +.endif + +.endif # !target(____) Index: head/share/mk/bsd.dep.mk =================================================================== --- head/share/mk/bsd.dep.mk +++ head/share/mk/bsd.dep.mk @@ -83,7 +83,7 @@ # Skip reading .depend when not needed to speed up tree-walks # and simple lookups. .if !empty(.MAKEFLAGS:M-V${_V_READ_DEPEND}) || make(obj) || make(clean*) || \ - make(install*) + make(install*) || make(analyze) _SKIP_READ_DEPEND= 1 .if ${MK_DIRDEPS_BUILD} == "no" .MAKE.DEPENDFILE= /dev/null Index: head/share/mk/bsd.lib.mk =================================================================== --- head/share/mk/bsd.lib.mk +++ head/share/mk/bsd.lib.mk @@ -441,5 +441,6 @@ .endif .include +.include .include .include Index: head/share/mk/bsd.prog.mk =================================================================== --- head/share/mk/bsd.prog.mk +++ head/share/mk/bsd.prog.mk @@ -283,5 +283,6 @@ .endif .include +.include .include .include Index: head/share/mk/bsd.subdir.mk =================================================================== --- head/share/mk/bsd.subdir.mk +++ head/share/mk/bsd.subdir.mk @@ -39,7 +39,7 @@ ____: SUBDIR_TARGETS+= \ - all all-man buildconfig buildfiles buildincludes \ + all all-man analyze buildconfig buildfiles buildincludes \ checkdpadd clean cleandepend cleandir cleanilinks \ cleanobj depend distribute files includes installconfig \ installfiles installincludes realinstall lint maninstall \ Index: head/share/mk/bsd.sys.mk =================================================================== --- head/share/mk/bsd.sys.mk +++ head/share/mk/bsd.sys.mk @@ -176,7 +176,7 @@ # Tell bmake not to mistake standard targets for things to be searched for # or expect to ever be up-to-date. -PHONY_NOTMAIN = afterdepend afterinstall all beforedepend beforeinstall \ +PHONY_NOTMAIN = analyze afterdepend afterinstall all beforedepend beforeinstall \ beforelinking build build-tools buildconfig buildfiles \ buildincludes check checkdpadd clean cleandepend cleandir \ cleanobj configure depend distclean distribute exe \ Index: head/sys/conf/kmod.mk =================================================================== --- head/sys/conf/kmod.mk +++ head/sys/conf/kmod.mk @@ -461,5 +461,6 @@ .endif .include +.include .include .include "kern.mk"