diff --git a/GNUmakefile b/GNUmakefile index 3c10e1f7ff..8cb5d3e486 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -1,103 +1,61 @@ # # Copyright 2008-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # default: build .PHONY: default -# The toplevel "clean" targets are generated from Makefile.am, not this file. -# We can't use autotools' CLEANFILES, clean-local, etc. here. Instead, we -# define this target, which Makefile.am can use as a dependency of clean-local. -EXTRA_CLEAN_TARGETS = ancillary-clean - -include Makefile # The main purpose of this GNUmakefile is that its targets can be invoked # without having to call autogen.sh and configure first. That means automake # variables may or may not be defined. Here, we use the current working # directory if a relevant variable hasn't been defined. abs_srcdir ?= $(shell pwd) GLIB_CFLAGS ?= $(pkg-config --cflags glib-2.0) PACKAGE ?= pacemaker .PHONY: init init: test -e configure && test -e libltdl || ./autogen.sh test -e Makefile || ./configure .PHONY: build build: init $(MAKE) $(AM_MAKEFLAGS) core ## RPM-related targets (deprecated; use targets in rpm subdirectory instead) # Pass option depending on whether automake has been run or not USE_FILE = $(shell test -e rpm/Makefile || echo "-f Makefile.am") .PHONY: $(PACKAGE).spec chroot dirty export mock rc release rpm rpmlint srpm $(PACKAGE).spec chroot dirty export mock rc release rpm rpmlint srpm: $(MAKE) $(AM_MAKEFLAGS) -C rpm $(USE_FILE) "$@" .PHONY: mock-% rpm-% spec-% srpm-% mock-% rpm-% spec-% srpm-%: $(MAKE) $(AM_MAKEFLAGS) -C rpm $(USE_FILE) "$@" -## Targets that moved to devel subdirectory +## Development-related targets +## (deprecated; use targets in devel subdirectory instead) -COVLEVEL ?= low +COVLEVEL ?= low +COVERAGE_TARGETS = coverage coverage-cts coverage-clean +COVERITY_TARGETS = coverity coverity-analyze coverity-clean coverity-corp -.PHONY: clang cppcheck indent -.PHONY: coverity coverity-analyze coverity-clean coverity-corp -clang coverity coverity-analyze coverity-clean coverity-corp cppcheck indent: +.PHONY: clang $(COVERAGE_TARGETS) $(COVERITY_TARGETS) cppcheck indent +clang $(COVERAGE_TARGETS) $(COVERITY_TARGETS) cppcheck indent: @echo 'Deprecated: Use "make -C devel $@" instead' $(MAKE) $(AM_MAKEFLAGS) \ CLANG_checkers=$(CLANG_checkers) \ COVLEVEL=$(COVLEVEL) \ CPPCHECK_ARGS=$(CPPCHECK_ARGS) \ -C devel "$@" - - -## Coverage/profiling - -.PHONY: coverage -coverage: core - -find . -name "*.gcda" -exec rm -f \{\} \; - -rm -rf coverage - lcov --no-external --exclude='*_test.c' -c -i -d . -o pacemaker_base.info - $(MAKE) $(AM_MAKEFLAGS) check - lcov --no-external --exclude='*_test.c' -c -d . -o pacemaker_test.info - lcov -a pacemaker_base.info -a pacemaker_test.info -o pacemaker_total.info - genhtml pacemaker_total.info -o coverage -s - -.PHONY: coverage-cts -coverage-cts: core - -find . -name "*.gcda" -exec rm -f \{\} \; - -rm -rf coverage - lcov --no-external -c -i -d tools -o pacemaker_base.info - cts/cts-cli - lcov --no-external -c -d tools -o pacemaker_test.info - lcov -a pacemaker_base.info -a pacemaker_test.info -o pacemaker_total.info - genhtml pacemaker_total.info -o coverage -s - -# This target removes all coverage-related files. It is only to be run when -# done with coverage analysis and you are ready to go back to normal development, -# starting with re-running ./configure. It is not to be run in between -# "make coverage" runs. -# -# In particular, the *.gcno files are generated when the source is built. -# Removing those files will break "make coverage" until the whole source tree -# has been built and the *.gcno files generated again. -.PHONY: coverage-clean -coverage-clean: - -rm -f pacemaker_*.info - -rm -rf coverage - -find . \( -name "*.gcno" -o -name "*.gcda" \) -exec rm -f \{\} \; - -ancillary-clean: coverage-clean diff --git a/Makefile.am b/Makefile.am index 78c8e19ebc..df12b27175 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,129 +1,123 @@ # # Copyright 2003-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # # This directory must be same as in configure.ac's AC_CONFIG_MACRO_DIR ACLOCAL_AMFLAGS = -I m4 EXTRA_DIST = CONTRIBUTING.md \ GNUmakefile \ INSTALL.md \ README.markdown \ autogen.sh \ m4/CC_CHECK_LDFLAGS.m4 \ m4/CHECK_ENUM_VALUE.m4 \ m4/gnulib-cache.m4 \ m4/gnulib-tool.m4 \ m4/PKG_CHECK_VAR.m4 \ m4/REQUIRE_HEADER.m4 \ m4/version.m4 DISTCLEANFILES = config.status MAINTAINERCLEANFILES = Makefile.in \ aclocal.m4 \ config.guess \ config.sub \ configure \ depcomp \ install-sh \ ltmain.sh \ missing \ py-compile \ test-driver # Don't try to install files outside build directory for "make distcheck". AM_DISTCHECK_CONFIGURE_FLAGS = --prefix="$$dc_install_base/usr" \ --sysconfdir="$$dc_install_base/etc" \ --with-initdir="$$dc_install_base/etc/init.d" \ --with-ocfdir="$$dc_install_base/usr/lib/ocf" \ --with-systemdsystemunitdir="$$dc_install_base$(systemdsystemunitdir)" # Only these will get installed with a plain "make install" CORE_INSTALL = replace include lib daemons tools xml po python # Only these will get built with a plain "make" or "make clean" CORE = $(CORE_INSTALL) cts rpm SUBDIRS = $(CORE) devel doc etc extra maint tests AM_CPPFLAGS = -I$(top_srcdir)/include doc_DATA = README.markdown COPYING licensedir = $(docdir)/licenses/ dist_license_DATA = $(wildcard licenses/*) # Directories that should be created on install and removed on uninstall ## owned by root:haclient, mode 0750 ROOT_DIRS = $(PACEMAKER_CONFIG_DIR) ## owned by hacluster:haclient, mode 0750 DAEMON_R_DIRS = $(CRM_CONFIG_DIR) \ $(CRM_CORE_DIR) \ $(CRM_BLACKBOX_DIR) ## owned by hacluster:haclient, mode 0770 DAEMON_RW_DIRS = $(CRM_BUNDLE_DIR) \ $(CRM_LOG_DIR) core: @echo "Building only core components and tests: $(CORE)" @for subdir in $(CORE); do \ echo "Building $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir all || exit 1; \ done core-install: @echo "Installing only core components: $(CORE_INSTALL)" @for subdir in $(CORE_INSTALL); do \ echo "Installing $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir install || exit 1; \ done core-clean: @echo "Cleaning only core components and tests: $(CORE)" @for subdir in $(CORE); do \ echo "Cleaning $$subdir"; \ $(MAKE) $(AM_MAKEFLAGS) -C $$subdir clean || exit 1; \ done install-exec-local: for DIR in $(ROOT_DIRS) $(DAEMON_R_DIRS); do \ $(INSTALL) -d -m 750 "$(DESTDIR)/$$DIR"; \ done for DIR in $(DAEMON_RW_DIRS); do \ $(INSTALL) -d -m 770 "$(DESTDIR)/$$DIR"; \ done -for DIR in $(ROOT_DIRS); do \ chgrp $(CRM_DAEMON_GROUP) "$(DESTDIR)/$$DIR"; \ done -for DIR in $(DAEMON_R_DIRS) $(DAEMON_RW_DIRS); do \ chown $(CRM_DAEMON_USER):$(CRM_DAEMON_GROUP) "$(DESTDIR)/$$DIR"; \ done # Remove created directories only if they're empty uninstall-hook: -for DIR in $(ROOT_DIRS) $(DAEMON_R_DIRS) $(DAEMON_RW_DIRS); do \ rmdir "$(DESTDIR)/$$DIR"; \ done clean-generic: -rm -f *.tar.bz2 *.sed PACKAGE ?= pacemaker -# In a normal build, this file is included by GNUmakefile, which serves as the -# "real" makefile. But in a VPATH build, GNUmakefile won't exist in the build -# tree, and this file will be the "real" makefile. EXTRA_CLEAN_TARGETS handles -# both cases: GNUmakefile defines it before including this file, so the -# clean-local target can clean up files created by GNUmakefile targets. -# If this file is used alone, the variable will be undefined. -clean-local: $(EXTRA_CLEAN_TARGETS) +clean-local: -rm -f $(builddir)/$(PACKAGE)-*.tar.gz distclean-local: -rm -rf libltdl autom4te.cache diff --git a/devel/Makefile.am b/devel/Makefile.am index b544b8ae44..94581e1e9e 100644 --- a/devel/Makefile.am +++ b/devel/Makefile.am @@ -1,245 +1,295 @@ # -# Copyright 2020-2022 the Pacemaker project contributors +# Copyright 2020-2023 the Pacemaker project contributors # # The version control history for this file may have further details. # # This source code is licensed under the GNU General Public License version 2 # or later (GPLv2+) WITHOUT ANY WARRANTY. # include $(top_srcdir)/mk/common.mk include $(top_srcdir)/mk/release.mk # Coccinelle is a tool that takes special patch-like files (called semantic patches) and # applies them throughout a source tree. This is useful when refactoring, changing APIs, # catching dangerous or incorrect code, and other similar tasks. It's not especially # easy to write a semantic patch but most users should only be concerned about running # the target and inspecting the results. # # Documentation (including examples, which are the most useful): # https://coccinelle.gitlabpages.inria.fr/website/docs/ # # Run the "make cocci" target to just output what would be done, or "make cocci-inplace" # to apply the changes to the source tree. # # COCCI_FILES may be set on the command line, if you want to test just a single file # while it's under development. Otherwise, it is a list of all the files that are ready # to be run. # # ref-passed-variables-inited.cocci seems to be returning some false positives around # GHashTableIters, so it is disabled for the moment. COCCI_FILES ?= coccinelle/string-any-of.cocci \ coccinelle/string-empty.cocci \ coccinelle/string-null-matches.cocci \ coccinelle/use-func.cocci dist_noinst_SCRIPTS = coccinelle/test/testrunner.sh EXTRA_DIST = README gdbhelpers $(COCCI_FILES) \ coccinelle/ref-passed-variables-inited.cocci \ coccinelle/rename-fn.cocci \ coccinelle/test/ref-passed-variables-inited.input.c \ coccinelle/test/ref-passed-variables-inited.output # Any file in this list is allowed to use any of the pcmk__ internal functions. # Coccinelle can use any transformation that depends on "internal" to rewrite # code to use the internal functions. MAY_USE_INTERNAL_FILES = $(shell find .. -path "../lib/*.c" -o -path "../lib/*private.h" -o -path "../tools/*.c" -o -path "../daemons/*.c" -o -path '../include/pcmki/*h' -o -name '*internal.h') # And then any file in this list is public API, which may not use internal # functions. Thus, only those transformations that do not depend on "internal" # may be applied. OTHER_FILES = $(shell find ../include -name '*h' -a \! -name '*internal.h' -a \! -path '../include/pcmki/*') cocci: -for cf in $(COCCI_FILES); do \ for f in $(MAY_USE_INTERNAL_FILES); do \ spatch $(_SPATCH_FLAGS) -D internal --very-quiet --local-includes --preprocess --sp-file $$cf $$f; \ done ; \ for f in $(OTHER_FILES); do \ spatch $(_SPATCH_FLAGS) --very-quiet --local-includes --preprocess --sp-file $$cf $$f; \ done ; \ done cocci-inplace: $(MAKE) $(AM_MAKEFLAGS) _SPATCH_FLAGS=--in-place cocci cocci-test: for f in coccinelle/test/*.c; do \ coccinelle/test/testrunner.sh $$f; \ done # # Static analysis # ## clang # See scan-build(1) for possible checkers (leave empty to use default set) CLANG_checkers ?= clang: OUT=$$(cd $(top_builddir) \ && scan-build $(CLANG_checkers:%=-enable-checker %) \ $(MAKE) $(AM_MAKEFLAGS) CFLAGS="-std=c99 $(CFLAGS)" \ clean all 2>&1); \ REPORT=$$(echo "$$OUT" \ | sed -n -e "s/.*'scan-view \(.*\)'.*/\1/p"); \ [ -z "$$REPORT" ] && echo "$$OUT" || scan-view "$$REPORT" ## coverity # Aggressiveness (low, medium, or high) COVLEVEL ?= low # Generated outputs COVERITY_DIR = $(abs_top_builddir)/coverity-$(TAG) COVTAR = $(abs_top_builddir)/$(PACKAGE)-coverity-$(TAG).tgz COVEMACS = $(abs_top_builddir)/$(TAG).coverity COVHTML = $(COVERITY_DIR)/output/errors # Coverity outputs are phony so they get rebuilt every invocation .PHONY: $(COVERITY_DIR) $(COVERITY_DIR): coverity-clean $(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir) init core-clean $(AM_V_GEN)cd $(top_builddir) \ && cov-build --dir "$@" $(MAKE) $(AM_MAKEFLAGS) core # Public coverity instance .PHONY: $(COVTAR) $(COVTAR): $(COVERITY_DIR) $(AM_V_GEN)tar czf "$@" --transform="s@.*$(TAG)@cov-int@" "$<" .PHONY: coverity coverity: $(COVTAR) @echo "Now go to https://scan.coverity.com/users/sign_in and upload:" @echo " $(COVTAR)" @echo "then make clean at the top level" # Licensed coverity instance # # The prerequisites are a little hacky; rather than actually required, some # of them are designed so that things execute in the proper order (which is # not the same as GNU make's order-only prerequisites). .PHONY: coverity-analyze coverity-analyze: $(COVERITY_DIR) @echo "" @echo "Analyzing (waiting for coverity license if necessary) ..." cd $(top_builddir) && cov-analyze --dir "$<" --wait-for-license \ --security --aggressiveness-level "$(COVLEVEL)" .PHONY: $(COVEMACS) $(COVEMACS): coverity-analyze $(AM_V_GEN)cd $(top_builddir) \ && cov-format-errors --dir "$(COVERITY_DIR)" --emacs-style > "$@" .PHONY: $(COVHTML) $(COVHTML): $(COVEMACS) $(AM_V_GEN)cd $(top_builddir) \ && cov-format-errors --dir "$(COVERITY_DIR)" --html-output "$@" .PHONY: coverity-corp coverity-corp: $(COVHTML) $(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir) core-clean @echo "Done. See:" @echo " file://$(COVHTML)/index.html" @echo "When no longer needed, make coverity-clean" # Remove all outputs regardless of tag .PHONY: coverity-clean coverity-clean: -rm -rf "$(abs_builddir)"/coverity-* \ "$(abs_builddir)"/$(PACKAGE)-coverity-*.tgz \ "$(abs_builddir)"/*.coverity ## cppcheck # Use CPPCHECK_ARGS to pass extra cppcheck options, e.g.: # --enable={warning,style,performance,portability,information,all} # --inconclusive --std=posix # -DBUILD_PUBLIC_LIBPACEMAKER -DDEFAULT_CONCURRENT_FENCING_TRUE CPPCHECK_ARGS ?= CPPCHECK_DIRS = replace lib daemons tools CPPCHECK_OUT = $(abs_top_builddir)/cppcheck.out cppcheck: cppcheck $(CPPCHECK_ARGS) -I $(top_srcdir)/include \ --output-file=$(CPPCHECK_OUT) \ --max-configs=30 --inline-suppr -q \ --library=posix --library=gnu --library=gtk \ $(GLIB_CFLAGS) -D__GNUC__ \ $(foreach dir,$(CPPCHECK_DIRS),$(top_srcdir)/$(dir)) @echo "Done: See $(CPPCHECK_OUT)" @echo "When no longer needed, make cppcheck-clean" .PHONY: cppcheck-clean cppcheck-clean: -rm -f "$(CPPCHECK_OUT)" +# +# Coverage/profiling +# + +COVERAGE_DIR = $(top_builddir)/coverage + +# Check coverage of unit tests +.PHONY: coverage +coverage: coverage-partial-clean + cd $(top_builddir) \ + && $(MAKE) $(AM_MAKEFLAGS) core \ + && lcov --no-external --exclude='*_test.c' -c -i -d . \ + -o pacemaker_base.info \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && lcov --no-external --exclude='*_test.c' -c -d . \ + -o pacemaker_test.info \ + && lcov -a pacemaker_base.info -a pacemaker_test.info \ + -o pacemaker_total.info + genhtml $(top_builddir)/pacemaker_total.info -o $(COVERAGE_DIR) -s + +# Check coverage of CLI regression tests +.PHONY: coverage-cts +coverage-cts: coverage-partial-clean + cd $(top_builddir) \ + && $(MAKE) $(AM_MAKEFLAGS) core \ + && lcov --no-external -c -i -d tools -o pacemaker_base.info \ + && cts/cts-cli \ + && lcov --no-external -c -d tools -o pacemaker_test.info \ + && lcov -a pacemaker_base.info -a pacemaker_test.info \ + -o pacemaker_total.info + genhtml $(top_builddir)/pacemaker_total.info -o $(COVERAGE_DIR) -s + +# Remove coverage-related files that aren't needed across runs +.PHONY: coverage-partial-clean +coverage-partial-clean: + -rm -f $(top_builddir)/pacemaker_*.info + -rm -rf $(COVERAGE_DIR) + -find $(top_builddir) -name "*.gcda" -exec rm -f \{\} \; + +# This target removes all coverage-related files. It is only to be run when +# done with coverage analysis and you are ready to go back to normal development, +# starting with re-running ./configure. It is not to be run in between +# "make coverage" runs. +# +# In particular, the *.gcno files are generated when the source is built. +# Removing those files will break "make coverage" until the whole source tree +# has been built and the *.gcno files generated again. +.PHONY: coverage-clean +coverage-clean: coverage-partial-clean + -find $(top_builddir) -name "*.gcno" -exec rm -f \{\} \; # # indent cannot cope with all our exceptions and needs heavy manual editing # # indent target: Limit indent to these directories INDENT_DIRS ?= . # indent target: Extra options to pass to indent INDENT_OPTS ?= INDENT_IGNORE_PATHS = daemons/controld/controld_fsa.h \ lib/gnu/* INDENT_PACEMAKER_STYLE = --blank-lines-after-declarations \ --blank-lines-after-procedures \ --braces-after-func-def-line \ --braces-on-if-line \ --braces-on-struct-decl-line \ --break-before-boolean-operator \ --case-brace-indentation4 \ --case-indentation4 \ --comment-indentation0 \ --continuation-indentation4 \ --continue-at-parentheses \ --cuddle-do-while \ --cuddle-else \ --declaration-comment-column0 \ --declaration-indentation1 \ --else-endif-column0 \ --honour-newlines \ --indent-label0 \ --indent-level4 \ --line-comments-indentation0 \ --line-length80 \ --no-blank-lines-after-commas \ --no-comment-delimiters-on-blank-lines \ --no-space-after-function-call-names \ --no-space-after-parentheses \ --no-tabs \ --preprocessor-indentation2 \ --procnames-start-lines \ --space-after-cast \ --start-left-side-of-comments \ --swallow-optional-blank-lines \ --tab-size8 indent: VERSION_CONTROL=none \ find $(INDENT_DIRS) -type f -name "*.[ch]" \ $(INDENT_IGNORE_PATHS:%= ! -path '%') \ -exec indent $(INDENT_PACEMAKER_STYLE) $(INDENT_OPTS) \{\} \; # # Scratch file for ad-hoc testing # EXTRA_PROGRAMS = scratch nodist_scratch_SOURCES = scratch.c scratch_LDADD = $(top_builddir)/lib/common/libcrmcommon.la -clean-local: coverity-clean cppcheck-clean +clean-local: coverage-clean coverity-clean cppcheck-clean -rm -f $(EXTRA_PROGRAMS)