diff --git a/Makefile b/Makefile index ab760d6563c62eebd7d2d63cf327556092ea8913..81cce48e4319a4f780159c3f53c6d3c9c442931a 100644 --- a/Makefile +++ b/Makefile @@ -27,16 +27,14 @@ MAKECONFIG_DIR=share include $(MAKECONFIG_DIR)/Makefile.common ############################################################################## -# PTESTS SRC +# TOOLS CONFIG ################################ -FRAMAC_PTESTS_SRC:=tools/ptests - -############################################################################## -# HDRCK SRC -################################ +IN_FRAMAC:=yes +FRAMAC_PTESTS_SRC:=tools/ptests FRAMAC_HDRCK_SRC:=tools/hdrck +FRAMAC_LINTCK_SRC:=tools/lint ############################################################################## # Frama-C @@ -80,9 +78,6 @@ include ivette/Makefile.installation # HEADER MANAGEMENT ################################ -# HDRCK is internal -FRAMAC_HDRCK:=tools/hdrck/hdrck.exe - # Part that can be shared for external plugins include share/Makefile.headers @@ -112,8 +107,6 @@ include share/Makefile.testing # Linters ################################ -############################################################################### - # Code prettyfication and lint include share/Makefile.linting diff --git a/share/Makefile.headers b/share/Makefile.headers index 7e0beb06fc8fee2a3626bc86f3c1c9e892fc600a..47d53f56919bf8f90a6f3f0fd3c639e79d2feeed 100644 --- a/share/Makefile.headers +++ b/share/Makefile.headers @@ -28,7 +28,7 @@ # Parameters # Must be unset (for external plugins) and set (for FRAMA-C kernel) -FRAMAC_HDRCK?= +IN_FRAMAC?= HDRCK?=frama-c-hdrck @@ -50,22 +50,15 @@ HEADER_OPEN_SOURCE?=yes # - <dir>: directory containing the files to manage HEADER_REPO?= -# Can be set to a file -# - <file>: file containing the list of the files to manage -HEADER_DISTRIB_FILE?= +# Can be set to a +# - <file> containing files to check/update and their attributes, with 0 +# separators (like 'git ls-files -z | git check-attr --stdin -z header_spec'). +HDRCK_FILES_INPUT?= # Can be set to a file # - <file>: file containing the list of the files to ignore any way HEADER_EXCEPTIONS?= -# Can be set to a file -# - <files>: input file containing, for each file to manage, the "header_spec" attribute value -HEADER_SPEC?= - -# Can be set to a file -# - yes: save the "header_spec" attribute specification into the file "HEADER_SPEC" -HEADER_SAVE_SPEC?=no - # Extra parameters for "frama-c-hdrck" HDRCK_EXTRA?= @@ -74,82 +67,19 @@ HDRCK_EXTRA?= GIT ?= git DUNE ?= dune -TEE ?= tee ########################################################################## ## Command used to execute hdrck -# Note: the public name of hdrck.exe is frama-c-hdrck -ifeq ($(FRAMAC_HDRCK),) - -# HDRCK is external +ifneq ($(IN_FRAMAC),yes) HDRCK.CMD:= $(HDRCK) - else - -# HDRCK is internal HDRCK.CMD:= $(DUNE) exec --root $(FRAMAC_HDRCK_SRC) -- $(HDRCK) - -$(FRAMAC_HDRCK): tools/hdrck/hdrck.ml - $(DUNE) build --root $(FRAMAC_HDRCK_SRC) hdrck.exe - endif -HDRCK.OPTS:= --stdin - -###################################################################### -## Identifies how to get the header specification (from git/find/cat) -## and updates HDRCK.OPTS variable - -HDRCK.FILE_LIST=$(GIT) ls-files -z -HDRCK.FILE_ATTR=$(GIT) check-attr --stdin -z header_spec - -ifeq ($(HEADER_SPEC),) - -HDRCK.HAS_GIT:=$(shell git rev-parse --is-inside-work-tree 2> /dev/null) -ifeq ($(HDRCK.HAS_GIT),true) - -# From git (including git work-trees) -HDRCK.SPEC:=$(HDRCK.FILE_LIST) | $(HDRCK.FILE_ATTR) -HDRCK.OPTS+= -z - -else - -# Note: in such a case, GIT is required... -HDRCK.SPEC:= - -endif # HDRCK.HAS_GIT - -else # HEADER_SPEC - -ifeq ($(HEADER_SAVE_SPEC),yes) - -HDRCK.HAS_GIT:=$(shell git rev-parse --is-inside-work-tree 2> /dev/null) -ifeq ($(HDRCK.HAS_GIT),true) - -# From git (including git work-trees) -HDRCK.SPEC:= $(HDRCK.FILE_LIST) | $(HDRCK.FILE_ATTR) | $(TEE) $(HEADER_SPEC) -HDRCK.OPTS+= -z - -else - -# Note: in such a case, GIT is required... -HDRCK.SPEC:= - -endif # HDRCK.HAS_GIT - -else # HEADER_SAVE_SPEC - -# From a file -HDRCK.SPEC:= cat $(HEADER_SPEC) - -# The file format can be overloaded in using the var HDRCK_EXTRA -HDRCK.OPTS+= -spec-format 3-zeros +HDRCK.OPTS:= --stdin -z -spec-format 3-zeros -endif # HEADER_SAVE_SPEC -endif # HEADER_SPEC - -################################ +########################################################################## ## Updates HDRCK.OPTS variable ifneq ($(HEADER_DISTRIB_FILE),) @@ -172,9 +102,8 @@ ifeq ($(HEADER_STRICT),yes) HDRCK.OPTS+= -exit-on-warning endif -##################################### -## Identifies where are the headers -## and updates HDRCK.OPTS variable +########################################################################## +## Identifies where are the headers and updates HDRCK.OPTS variable ifeq ($(HEADER_OPEN_SOURCE),yes) HDRCK.OPTS+= $(addprefix -header-dirs=,$(addsuffix /open-source,$(HEADER_DIRS))) @@ -190,134 +119,45 @@ endif endif endif -################################# - -ifeq ($(HDRCK.SPEC),) - -.PHONY: check-headers -check-headers: $(FRAMAC_HDRCK) - $(error "Please set HEADER_SPEC variable to a file containing the header specification.") +########################################################################## +## HDRCK +HDRCK.HAS_GIT:=$(shell git rev-parse --is-inside-work-tree 2> /dev/null) +ifneq ($(HDRCK.HAS_GIT),true) +ifeq ($(HDRCK_FILES_INPUT),) +$(error "Cannot check or make headers: not a Git repository, \ + you should specify HDRCK_FILES_INPUT") +endif +endif -.PHONY: headers -headers: $(FRAMAC_HDRCK) - $(error "Please set HEADER_SPEC variable to a file containing the header specification.") +ifeq ($(HDRCK_FILES_INPUT),) +HDRCK.COLLECT=$(GIT) ls-files -z | $(GIT) check-attr --stdin -z header_spec else - -ifneq ($(HDRCK.HAS_GIT),) - -define HDRCK.file-list-from-git-diff-info -$(GIT) diff --name-status $(1) | $(GREP) -v "^D" | $(SED) -e "s/^[CR][0-9]\+[ \t]\+[^ \t]\+[ \t]\+//" -e "s/^[AM][ \t]*//" -endef - -define HDRCK.file-list-from-git-diff - $(call HDRCK.file-list-from-git-diff-info,$(1)) | $(TR) '\n' '\000' | $(HDRCK.FILE_ATTR) -endef - -HDRCK.main-targets=check-headers headers -define HDRCK.file-list-filter-with-git-diff -HDRCK.$(1)-filter-targets=$$(addsuffix .$(1),$$(HDRCK.main-targets)) -.PHONY: $(LINT.$(1)-filter-targets) -$$(HDRCK.$(1)-filter-targets):: HDRCK.SPEC=$$(call HDRCK.file-list-from-git-diff,$(2)) -$$(HDRCK.$(1)-filter-targets):: %.$(1) : $(3) % - @echo [HDRCK] Done: HDRCK_DIFF=\"$(2)\" make $$(basename $$@) - @echo [HDRCK] checked file list: - $$(call HDRCK.file-list-from-git-diff-info,$(2)) -endef - -ifneq ($(HEADER_DIFF),) - -$(info [HDRCK] Looking at files modified from branch/commit: '$(HEADER_DIFF)') -HDRCK.SPEC=$(call LINT.file-list-from-git-diff,$(HEADER_DIFF)) -$(info $(HEADER.FILE_LIST)) - -endif # $(HEADER_DIFF) - -#### rules for make <headers-target>.before-push -## looks at files modified from origin/$(git rev-parse --abbrev-ref HEAD) and checks that there is no staged nor unstaged files - -PHONY: HDRCK.checked-unmodified-ok -HDRCK.checked-unmodified-ok: - $(eval HDRCK.checked-unmodified := $(shell $(GIT) diff --name-status HEAD | $(WC) -l)) - if [ 0 != $(HDRCK.checked-unmodified) ]; then \ - echo "[HDRCK] Staged or unstaged files=$(HDRCK.checked-unmodified):"; \ - $(GIT) diff --name-status HEAD; \ - echo "[HDRCK] Error: may check some staged or unstaged file versions" ; \ - exit 1; \ - fi; - -$(eval $(call HDRCK.file-list-filter-with-git-diff,before-push,--cached origin/$(shell git rev-parse --abbrev-ref HEAD),HDRCK.checked-unmodified-ok)) - -#### rules for make <headers-target>.unstaged -## looks at unstaged files - -$(eval $(call HDRCK.file-list-filter-with-git-diff,unstaged, )) - -#### rules for make <headers-target>.before-commit -## looks at staged files and checks that there is no unstaged files - -PHONY: HDRCK.checked-unstaged-ok -HDRCK.checked-unstaged-ok: - $(eval HDRCK.checked-unstaged := $(shell $(GIT) diff --name-status | $(WC) -l)) - if [ 0 != $(HDRCK.checked-unstaged) ]; then \ - echo "[HDRCK] Unstaged files=$(HDRCK.checked-unstaged):"; \ - $(GIT) diff --name-status ; \ - echo "[HDRCK] Error: may check some unstaged version files version." ; \ - exit 1; \ - fi; - -$(eval $(call HDRCK.file-list-filter-with-git-diff,before-commit,--cached HEAD,HDRCK.checked-unstaged-ok)) - -#### rules for make <headers-target>.before-commit-a -## looks at unstaged and staged files - -$(eval $(call HDRCK.file-list-filter-with-git-diff,before-commit-a,HEAD,)) - -#### rules for make <headers-target>.before-commit-a--ammend -## looks at unstaged, staged and previously committed files - -$(eval $(call HDRCK.file-list-filter-with-git-diff,before-commit-a--ammend,HEAD~1,)) - -#### rules for make <headers-target>.before-commit--amend -## looks at staged and previously committed files and checks that there is no unstaged files - -$(eval $(call HDRCK.file-list-filter-with-git-diff,before-commit--ammend,HEAD~1,HDRCK.checked-unstaged-ok)) - -#### rules for make <headers-target>.previous-commit -## looks at files of the last commit and checks that there is no staged nor unstaged files - -$(eval $(call HDRCK.file-list-filter-with-git-diff,previous-commit,HEAD~1,HDRCK.checked-unmodified-ok)) - -endif # $(HDRCK.HAS_GIT) +HDRCK.COLLECT=cat $(HDRCK_FILES_INPUT) +endif .PHONY: check-headers -check-headers: $(FRAMAC_HDRCK) - $(HDRCK.SPEC) | $(HDRCK.CMD) $(HDRCK.OPTS) $(HDRCK_EXTRA) +check-headers: + $(HDRCK.COLLECT) | $(HDRCK.CMD) $(HDRCK.OPTS) $(HDRCK_EXTRA) .PHONY: headers -headers: $(FRAMAC_HDRCK) - $(HDRCK.SPEC) | $(HDRCK.CMD) -update $(HDRCK.OPTS) $(HDRCK_EXTRA) - -endif # $(HDRCK.SPEC) +headers: + $(HDRCK.COLLECT) | $(HDRCK.CMD) -update $(HDRCK.OPTS) $(HDRCK_EXTRA) ################################# .PHONY: headers.info headers.info: - echo "FRAMAC_HDRCK='$(FRAMAC_HDRCK)'" echo "HEADER_OPEN_SOURCE='$(HEADER_OPEN_SOURCE)'" echo "HEADER_STRICT='$(HEADER_STRICT)'" echo "HEADER_DIRS='$(HEADER_STRICT)'" - echo "HEADER_DISTRIB_FILE='$(HEADER_DISTRIB_FILE)'" echo "HEADER_EXCEPTIONS='$(HEADER_EXCEPTIONS)'" echo "HEADER_REPO='$(HEADER_REPO)'" - echo "HEADER_SPEC='$(HEADER_SPEC)'" + echo "HDRCK_FILES_INPUT='$(HDRCK_FILES_INPUT)'" echo "HDRCK.HAS_GIT='$(HDRCK.HAS_GIT)'" echo "HDRCK.CMD='$(HDRCK.CMD)'" - echo "HDRCK.SPEC='$(HDRCK.SPEC)'" echo "HDRCK.OPTS='$(HDRCK.OPTS)'" - ############################################################################### # Local Variables: # compile-command: "make" diff --git a/share/Makefile.linting b/share/Makefile.linting index 373d0bf29ac34d1252d1c49bab25e553d0a2116e..4edf434164ee8aed58bfc6e2d41f8480e0b6a41e 100644 --- a/share/Makefile.linting +++ b/share/Makefile.linting @@ -20,555 +20,72 @@ # # ########################################################################## +########################################################################## +# Parameters -################################ -# Code prettyfication and lint # -################################ - -# make lint includes: -# - make check-utf8: valid UTF-8 encoding -# - make check-eoleof: EOF preceded by an EOL -# - make check-syntax: EOF preceded by an EOL + no TAB + no BLANK at the end -# - make check-indent: valid indentation -# -# For all these targets (and the corresponding fix-XXX), it is possible to restrict the search to a sub-directory: -# - make LINT_DIR=<subdir> <lint-target> -# It is possible to force the action to given files: -# - make LINT_FILE=<file> <lint-target> -# or to the files modified between HEAD and a specific branch/commit: -# - make LINT_DIFF=<branch/commit> <lint-target> -# -# Notes: -# - when LINT_FILE is given, .gitattributes, LINT_DIFF and LINT_DIR are ignored; -# - when LINT_DIFF is given, LINT_DIR is ignored (but .gitattributes is used); -# - to use fix-utf8 target, the variable LINT_FROM_ENCODING=<from-encoding-name> -# has to be set. -# -# Advanced targets when LINT_FILE is undefined -# - make <lint-target>.unstaged -# looks at unstaged files -# - make <lint-target>.before-commit-a -# looks at unstaged and staged files -# - make <lint-target>.before-commit-a--amend -# looks at unstaged, staged and previously committed files -# - make <lint-target>.before-commit--amend -# looks at staged and previously committed files and checks that there is no unstaged files -# - make <lint-target>.before-commit -# looks at staged files and checks that there is no unstaged files -# - make <lint-target>.previous-commit -# looks at files of the last commit and checks that there is no staged nor unstaged files -# - make <lint-target>.before-push: -# looks at files modified from origin/$(git rev-parse --abbrev-ref HEAD) and checks that there is no staged nor unstaged files +# Must be unset (for external plugins) and set (for FRAMA-C kernel) +IN_FRAMAC?= -# make clean-lint (removing linting targets) includes -# - make clean-utf8 -# - make clean-eoleof -# - make clean-syntax -# - make clean-indent +# Note: DO NOT rename this variable "LINT", this name is defined in GNU Makefile +LINTCK?=frama-c-lint -# make clean-lint (removing linting targets) includes -# - make clean-utf8 -# - make clean-eoleof -# - make clean-syntax -# - make clean-indent +# Can be set to a +# - <file> containing files to check/update and their attributes, with 0 +# separators (like 'git ls-files -z | git check-attr --stdin -za'). +LINTCK_FILES_INPUT?= -################################ -## Default variables +# Extra parameters for the lint command +LINTCK_EXTRA?= -IS_UTF8 ?= iconv -f UTF-8 -t UTF-8 -TO_UTF8 ?= iconv -t UTF-8 -f +########################################################################## +## Tools -OCP_INDENT ?= ocp-indent -CLANG_FORMAT ?= clang-format -# wc, tail, head, cmp +GIT ?= git +DUNE ?= dune -# Default values necessary for -# LINT_MAKEFILE=<this-makefile> make -f <this-makefile> <lint-target>` -# Otherwise theses variables are defined into share/Makefile.common -GREP ?= grep -TR ?= tr -SED ?= LC_ALL=C sed -ISED ?= sed -i -FIND ?= find -GIT ?= git -MKDIR ?= mkdir -p -MV ?= mv -RM ?= rm -f -RMDIR ?= rm -rf -TOUCH ?= touch -WC ?= wc +########################################################################## +## Command used to execute lint -ifeq ($(PLATFORM),Darwin) -XARGS ?= xargs +ifneq ($(IN_FRAMAC),yes) +LINTCK.CMD:= $(LINTCK) else -# Unix, Cygwin -XARGS ?= xargs --no-run-if-empty +LINTCK.CMD:= $(DUNE) exec --root $(FRAMAC_LINTCK_SRC) -- $(LINTCK) endif -############ - -# Can be set to the path of that makefile -LINT_MAKEFILE ?= - -# Can be set to a sub-directory to restrict the checking -LINT_DIR ?= . - -################################ - -LINT.makefile=$(wildcard $(LINT_MAKEFILE)) -ifeq ($(LINT.makefile),) - -LINT.make?=$(MAKE) --quiet -else +########################################################################## +## LINT -LINT.make?=$(MAKE) --quiet -f $(LINT.makefile) +LINTCK.HAS_GIT:=$(shell git rev-parse --is-inside-work-tree 2> /dev/null) +ifneq ($(LINTCK.HAS_GIT),true) +ifeq ($(LINTCK_FILES_INPUT),) +$(error "Cannot lint: not a Git repository, \ + you should specify LINTCK_FILES_INPUT") endif - -################################ -## CHECK ocp-indent VERSION - -.lint/check-ocp-indent-version: - if command -v $(OCP_INDENT) >/dev/null; then \ - if [ -z "$(shell $(OCP_INDENT) --version)" ]; then echo "warning: $(OCP_INDENT) returned an empty string, assuming it is the correct version"; \ - else \ - $(eval ocp_version_major := $(shell $(OCP_INDENT) --version | $(SED) -E "s/^([0-9]+)\.[0-9]+\..*/\1/")) \ - $(eval ocp_version_minor := $(shell $(OCP_INDENT) --version | $(SED) -E "s/^[0-9]+\.([0-9]+)\..*/\1/")) \ - if [ "$(ocp_version_major)" -lt 1 -o "$(ocp_version_minor)" -lt 7 ]; then \ - echo "error: $(OCP_INDENT) 1.7.0 required for linting (got $(ocp_version_major).$(ocp_version_minor))"; \ - exit 1; \ - fi; \ - fi; \ - else \ - exit 1; \ - fi; - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -.lint/check-clang-format-installed: - if ! command -v $(CLANG_FORMAT) >/dev/null; then \ - echo "error: $(CLANG_FORMAT) must be installed"; \ - exit 1; \ - fi; - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -############### -## Main target - -LINT.check-targets= \ - check-syntax check-indent check-eoleof check-utf8 - -LINT.fix-targets=$(subst check-,fix-,$(LINT.check-targets)) -LINT.main-targets=lint $(LINT.check-targets) $(LINT.fix-targets) - -LINT.HAS_GIT:=$(shell git rev-parse --is-inside-work-tree 2> /dev/null) -ifneq ($(LINT.HAS_GIT),true) - -.PHONY: lint -lint: - echo "'make lint' requires a git repository but, that is not" - echo "the case for example with 'make LINT_FILE=<file> check-syntax'" - git rev-parse --is-inside-work-tree - -else - -.PHONY: lint -lint: $(LINT.check-targets) - endif -############################### -## Cleaning - -# Targets are generated into .lint/ directories - -.PHONY: clean-lint -clean-lint: - echo "Cleaning LINT targets..." - $(RMDIR) .lint - -clean:: clean-lint - -#### clean-check-XXX targets - -LINT.clean-targets=$(addprefix clean-,$(LINT.check-targets)) - -.PHONY: $(LINT.clean-targets) -# Generic rule -$(LINT.clean-targets): - echo "[LINT] Cleaning $(patsubst clean-%,%,$@) targets..." - $(FIND) .lint -type f -name \*.$(patsubst clean-%,%,$@) | $(XARGS) -n 10 $(RM) - -############################### - -ifeq ($(LINT_FILE),) ############# No lint file given - -######## LINT_DIR filter -LINT.dir=$(wildcard $(LINT_DIR)) - -ifeq ($(LINT.HAS_GIT),true) ############# For Git repository - -######## LINT_DIFF filter - -define LINT.file-list-from-git-diff-info -$(GIT) diff --name-status $(1) | $(GREP) -v "^D" | $(SED) -e "s/^[CR][0-9]\+[ \t]\+[^ \t]\+[ \t]\+//" -e "s/^[AM][ \t]*//" -endef - -define LINT.file-list-from-git-diff -$(call LINT.file-list-from-git-diff-info,$(1)) | $(TR) '\n' '\000' -endef - -define LINT.file-list-filter-with-git-diff -LINT.$(1)-filter-targets=$$(addsuffix .$(1),$$(LINT.main-targets)) -.PHONY: $(LINT.$(1)-filter-targets) -$$(LINT.$(1)-filter-targets):: LINT.FILE_LIST=$$(call LINT.file-list-from-git-diff,$(2)) -$$(LINT.$(1)-filter-targets):: %.$(1) : $(3) % - @echo [LINT] Done: LINT_DIFF=\"$(2)\" make $$(basename $$@) - @echo [LINT] checked file list: - $$(call LINT.file-list-from-git-diff-info,$(2)) -endef - -ifeq ($(LINT_DIFF),) -LINT.FILE_LIST=$(GIT) ls-files $(LINT.dir) -z +ifeq ($(LINTCK_FILES_INPUT),) +LINTCK.COLLECT=$(GIT) ls-files -z | $(GIT) check-attr --stdin -z -a else -$(info [LINT] Looking at files modified from branch/commit: '$(LINT_DIFF)') -LINT.FILE_LIST=$(call LINT.file-list-from-git-diff,$(LINT_DIFF)) -$(info $(LINT.FILE_LIST)) +LINTCK.COLLECT=cat $(LINTCK_FILES_INPUT) endif -#### rules for make <lint-target>.before-push -## looks at files modified from origin/$(git rev-parse --abbrev-ref HEAD) and checks that there is no staged nor unstaged files - -PHONY: LINT.checked-unmodified-ok -LINT.checked-unmodified-ok: - $(eval LINT.checked-unmodified := $(shell $(GIT) diff --name-status HEAD | $(WC) -l)) - if [ 0 != $(LINT.checked-unmodified) ]; then \ - echo "[LINT] Staged or unstaged files=$(LINT.checked-unmodified):"; \ - $(GIT) diff --name-status HEAD; \ - echo "[LINT] Error: may check some staged or unstaged file versions" ; \ - exit 1; \ - fi; - -$(eval $(call LINT.file-list-filter-with-git-diff,before-push,--cached origin/$(shell git rev-parse --abbrev-ref HEAD),LINT.checked-unmodified-ok)) - -#### rules for make <lint-target>.unstaged -## looks at unstaged files - -$(eval $(call LINT.file-list-filter-with-git-diff,unstaged, )) - -#### rules for make <lint-target>.before-commit -## looks at staged files and checks that there is no unstaged files - -PHONY: LINT.checked-unstaged-ok -LINT.checked-unstaged-ok: - $(eval LINT.checked-unstaged := $(shell $(GIT) diff --name-status | $(WC) -l)) - if [ 0 != $(LINT.checked-unstaged) ]; then \ - echo "[LINT] Unstaged files=$(LINT.checked-unstaged):"; \ - $(GIT) diff --name-status ; \ - echo "[LINT] Error: may check some unstaged version files version." ; \ - exit 1; \ - fi; - -$(eval $(call LINT.file-list-filter-with-git-diff,before-commit,--cached HEAD,LINT.checked-unstaged-ok)) - -#### rules for make <lint-target>.before-commit-a -## looks at unstaged and staged files - -$(eval $(call LINT.file-list-filter-with-git-diff,before-commit-a,HEAD,)) - -#### rules for make <lint-target>.before-commit-a--amend -## looks at unstaged, staged and previously committed files - -$(eval $(call LINT.file-list-filter-with-git-diff,before-commit-a--amend,HEAD~1,)) - -#### rules for make <lint-target>.before-commit--amend -## looks at staged and previously committed files and checks that there is no unstaged files - -$(eval $(call LINT.file-list-filter-with-git-diff,before-commit--amend,HEAD~1,LINT.checked-unstaged-ok)) - -#### rules for make <lint-target>.previous-commit -## looks at files of the last commit and checks that there is no staged nor unstaged files - -$(eval $(call LINT.file-list-filter-with-git-diff,previous-commit,HEAD~1,LINT.checked-unmodified-ok)) - -#### get attr / filter set attr - -LINT.GET_ATTR=$(GIT) check-attr --stdin -z -LINT.FILTER_FILE_ATTR=$(SED) -zne 'x;n;n;s/^set$$//;t print;b;:print;x;p' - -#### check-XXX targets - -.PHONY: $(LINT.check-targets) -# Generic rule -$(LINT.check-targets): - echo "[LINT] Checking from GIT attribute $@..." - $(LINT.FILE_LIST) \ - | $(LINT.GET_ATTR) $@ \ - | $(LINT.FILTER_FILE_ATTR) \ - | $(XARGS) -0 -IXX sh -c '$(LINT.make) LINT_FILE="XX" $@ || exit 255' - -#### fix-XXX targets - -# Generic rule -$(LINT.fix-targets): - echo "[LINT] Fixing from GIT attribute $(patsubst fix-%,check-%,$@)..." - $(LINT.FILE_LIST) \ - | $(LINT.GET_ATTR) $(patsubst fix-%,check-%,$@) \ - | $(LINT.FILTER_FILE_ATTR) \ - | $(XARGS) -0 -IXX sh -c '$(LINT.make) LINT_FILE="XX" $@ || exit 255' - -endif ############ For Git repository - -else ############# LINT_FILE are given - -## Internal targets from the recursive make - -LINT_FILE.list=$(addprefix .lint/,$(wildcard $(LINT_FILE))) - -LINT_FILE.check-utf8= $(addsuffix .check-utf8,$(LINT_FILE.list)) -LINT_FILE.check-eoleof= $(addsuffix .check-eoleof,$(LINT_FILE.list)) -LINT_FILE.check-syntax= $(addsuffix .check-syntax,$(LINT_FILE.list)) -LINT_FILE.check-indent= $(addsuffix .check-indent,$(LINT_FILE.list)) - -LINT_FILE.fix-utf8= $(addsuffix .fix-utf8,$(LINT_FILE.list)) -LINT_FILE.fix-eoleof= $(addsuffix .fix-eoleof,$(LINT_FILE.list)) -LINT_FILE.fix-syntax= $(addsuffix .fix-syntax,$(LINT_FILE.list)) -LINT_FILE.fix-indent= $(addsuffix .fix-indent,$(LINT_FILE.list)) - -## Filters for the extension for check/fix-indent - -# ML filter -LINT_FILE.ml-indent = $(filter $(addsuffix .ml,$(basename $(LINT_FILE.list))),$(LINT_FILE.list)) -LINT_FILE.ml-indent+= $(filter $(addsuffix .mli,$(basename $(LINT_FILE.list))),$(LINT_FILE.list)) -LINT_FILE.check-ml-indent= $(addsuffix .check-indent,$(LINT_FILE.ml-indent)) -LINT_FILE.fix-ml-indent= $(addsuffix .fix-indent,$(LINT_FILE.ml-indent)) - -# C filter -LINT_FILE.c-indent =$(filter $(addsuffix .c,$(basename $(LINT_FILE.list))),$(LINT_FILE.list)) -LINT_FILE.c-indent+= $(filter $(addsuffix .h,$(basename $(LINT_FILE.list))),$(LINT_FILE.list)) -LINT_FILE.check-c-indent= $(addsuffix .check-indent,$(LINT_FILE.c-indent)) -LINT_FILE.fix-c-indent= $(addsuffix .fix-indent,$(LINT_FILE.c-indent)) - - -LINT_FILE.check-unknown-indent=$(filter-out $(LINT_FILE.check-ml-indent) \ - $(LINT_FILE.check-c-indent),$(LINT_FILE.check-indent)) -LINT_FILE.fix-unknown-indent=$(patsusbt %.check-indent,%.fix-indent,LINT_FILE.check-unknown-indent) - -## check-XXX targets - -.PHONY: check-utf8 -check-utf8: $(LINT_FILE.check-utf8) - -.PHONY: check-eoleof -check-eoleof: $(LINT_FILE.check-eoleof) - -.PHONY: check-syntax -check-syntax: $(LINT_FILE.check-syntax) - -# ML and C format -.PHONY: check-indent -check-indent: $(LINT_FILE.check-indent) - -## fix-XXX targets - -.PHONY: fix-utf8 -fix-utf8: $(LINT_FILE.fix-utf8) - -.PHONY: fix-eoleof -fix-eoleof: $(LINT_FILE.fix-eoleof) - -.PHONY: fix-syntax -fix-syntax: $(LINT_FILE.fix-syntax) - -# ML and C format -.PHONY: fix-indent -fix-indent: $(LINT_FILE.fix-indent) - -endif - -############################### -## UTF8 ASPECT - -$(LINT_FILE.check-utf8): .lint/%.check-utf8: % - echo "Check UTF8: $<" - if ! $(IS_UTF8) $< > /dev/null; \ - then \ - echo "File $< uses an invalid UTF-8 encoding."; \ - echo "Please fixe it manualy or in running: make LINT_FROM_ENCODING=<ENCODING-NAME> LINT_FILE=$< fix-utf8";\ - echo "The next command may help you to find that <ENCODING-NAME>: file $<";\ - exit 1; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -ifneq ($(LINT_FROM_ENCODING),) - -.PHONY: $(LINT_FILE.fix-utf8) -$(LINT_FILE.fix-utf8): .lint/%.fix-utf8: % - if ! $(IS_UTF8) $< > /dev/null 2> /dev/null; \ - then \ - echo "Fixes UTF8 (from $(LINT_FROM_ENCODING)): $<"; \ - if ! $(TO_UTF8) $(LINT_FROM_ENCODING) $< > $<.tmp; then exit 1; fi; \ - $(MV) $<.tmp $<; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) .lint/$<.check-utf8 # no more need of check-indent - -else - -$(LINT_FILE.fix-utf8): .lint/%.fix-utf8: % .lint/check-ocp-indent-version - $(error "Target fix-utf8 requires to define LINT_FROM_ENCODING variable") - -endif # LINT_FROM_ENCODING - -############################### -## UNKNOWN INDENTATION FORMATER - -ifneq ($(LINT_FILE.check-unknown-indent),) -.PHONY: $(LINT_FILE.check-unknown-indent) -$(LINT_FILE.check-unknown-indent): .lint/%.check-indent: % - $(error "Check indent with an unknown formater: $<") -endif - -ifneq ($(LINT_FILE.fix-unknown-indent),) -.PHONY: $(LINT_FILE.fix-unknown-indent) -$(LINT_FILE.check-unknown-indent): .lint/%.fix-indent: % - $(error "Check indent with an unknown formater: $<") -endif - -############################### -## ML INDENTATION ASPECT - -$(LINT_FILE.check-ml-indent): .lint/%.check-indent: % .lint/check-ocp-indent-version - echo "Check ML indent: $<" - $(OCP_INDENT) $< > $<.tmp - if cmp -s $< $<.tmp; \ - then $(RM) $<.tmp; \ - else \ - echo "File $< is not indented correctly."; \ - echo "Please run: make LINT_FILE=$< fix-indent";\ - $(RM) $<.tmp; \ - exit 1; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -.PHONY: $(LINT_FILE.fix-ml-indent) -$(LINT_FILE.fix-ml-indent): .lint/%.fix-indent: % .lint/check-ocp-indent-version - echo "Fixes ML indent: $<" - $(OCP_INDENT) -i $< - $(MKDIR) $(dir $@) - $(TOUCH) .lint/$<.check-indent # no more need of check-indent - -############################### -## C INDENTATION ASPECT - -$(LINT_FILE.check-c-indent): .lint/%.check-indent: % .lint/check-clang-format-installed - echo "Check C indent: $<" - $(CLANG_FORMAT) --dry-run -Werror $< - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -.PHONY: $(LINT_FILE.fix-c-indent) -$(LINT_FILE.fix-c-indent): .lint/%.fix-indent: % .lint/check-clang-format-installed - echo "Fixes C indent: $<" - $(CLANG_FORMAT) -i $< - $(MKDIR) $(dir $@) - $(TOUCH) .lint/$<.check-indent # no more need of check-indent - -############################### -## EOL EOF ASPECT (included by check-syntax target) - -$(LINT_FILE.check-eoleof): .lint/%.check-eoleof: % - # See SO 1825552 on mixing grep and \t (and cry) - # For OK_NL, we have three cases: - # - for empty files, the computation boils down to 0 - 0 == 0 - # - for non-empty files with a proper \n at the end, to 1 - 1 == 0 - # - for empty files without \n, to 1 - 0 == 1 that will be catched - echo "Check EOL EOF: $<" - OK_NL=$$(($$(tail -c -1 $< | wc -c) - $$(tail -n -1 $< | wc -l))) ; \ - if test $$OK_NL -gt 0; then \ - echo "File $< does not pass syntactic checks:"; \ - echo "No newline at end of file"; \ - echo "Please run: make LINT_FILE=$< fix-eoleof"; \ - exit 1 ; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -# The real target is a check-XXX one -.PHONY: $(LINT_FILE.fix-eoleof) -$(LINT_FILE.fix-eoleof): .lint/%.fix-eoleof: % - echo "Fixes EOL EOF: $<" - $(ISED) -e '$$a\' $< - $(MKDIR) $(dir $@) - $(TOUCH) .lint/$<.check-eoleof # no more need of this checking - -%.fix-eoleof: LC_ALL = C - -############################### -## SYNTACTICAL ASPECT - -$(LINT_FILE.check-syntax): .lint/%.check-syntax: % - # See SO 1825552 on mixing grep and \t (and cry) - # For OK_NL, we have three cases: - # - for empty files, the computation boils down to 0 - 0 == 0 - # - for non-empty files with a proper \n at the end, to 1 - 1 == 0 - # - for empty files without \n, to 1 - 0 == 1 that will be catched - echo "Check syntax: $<" - OK_TAB=$$(grep -c -e "$$(printf '^ *\t')" $<) ; \ - OK_SPACE=$$(grep -c -e '[[:blank:]]$$' $<) ; \ - OK_NL=$$(($$(tail -c -1 $< | wc -c) - $$(tail -n -1 $< | wc -l))) ; \ - OK_EMPTY=$$(tail -n -1 $< | grep -c -e '^[[:blank:]]*$$') ; \ - ERROR=$$(($$OK_TAB + $$OK_SPACE + $$OK_NL + $$OK_EMPTY)) ; \ - if test $$ERROR -gt 0; then \ - echo "File $< does not pass syntactic checks:"; \ - echo "$$OK_TAB lines indented with tabulation instead of spaces"; \ - echo "$$OK_SPACE lines with spaces at end of line"; \ - test $$OK_NL -eq 0 || echo "No newline at end of file"; \ - test $$OK_EMPTY -eq 0 || echo "Empty line(s) at end of file"; \ - echo "Please run: make LINT_FILE=$< fix-syntax"; \ - exit 1 ; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) $@ - -# The real target is a check-XXX one -.PHONY: $(LINT_FILE.fix-syntax) -$(LINT_FILE.fix-syntax): .lint/%.fix-syntax: % - echo "Fixes syntax: $<" - $(ISED) -e 's/^ *\t\+/ /' $< - $(ISED) -e 's/\(.*[^[:blank:]]\)[[:blank:]]\+$$/\1/' $< - $(ISED) -e 's/^[ \t]\+$$//' $< - if test \( $$(tail -n -1 $< | wc -l) -eq 0 \) -a \( $$(wc -c $< | cut -d " " -f 1) -gt 0 \) ; then \ - echo "" >> $<; \ - else \ - while tail -n -1 $< | grep -l -e '^[ \t]*$$'; do \ - head -n -1 $< > $<.tmp; \ - $(MV) $<.tmp $<; \ - done; \ - fi - $(MKDIR) $(dir $@) - $(TOUCH) .lint/$<.check-syntax # no more need of check-syntax +.PHONY: lint +lint: + $(LINTCK.COLLECT) | $(LINTCK.CMD) $(LINTCK_EXTRA) -# Avoid a UTF-8 locale at all cost: in such setting, sed does not work -# reliably if you happen to have latin-1 encoding somewhere, -# which is still unfortunately the case in some dark corners of the platform -%.fix-syntax: LC_ALL = C +.PHONY: fix-lint +fix-lint: + $(LINTCK.COLLECT) | $(LINTCK.CMD) -u $(LINTCK_EXTRA) -############################### -## Info +########################################################################## +.PHONY: lint.info lint.info: - echo "LINT.HAS_GIT='$(LINT.HAS_GIT)'" - echo "LINT.make='$(LINT.make)'" - echo "LINT_FILE.list='$(LINT_FILE.list)'" - echo "LINT_FILE.check-syntax='$(LINT_FILE.check-syntax)'" - echo "LINT_FILE.check-indent='$(LINT_FILE.check-indent)'" - echo "LINT_FILE.fix-syntax='$(LINT_FILE.fix-syntax)'" - echo "LINT_FILE.fix-indent='$(LINT_FILE.fix-indent)'" + echo "LINTCK_FILES_INPUT='$(LINTCK_FILES_INPUT)'" + echo "LINTCK.HAS_GIT='$(LINTCK.HAS_GIT)'" + echo "LINTCK.CMD='$(LINTCK.CMD)'" -############################################################################### +########################################################################## # Local Variables: # compile-command: "make" # End: