[gjs: 3/6] test: Add a CI job that ensures that PCH file is populated with all headers
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 3/6] test: Add a CI job that ensures that PCH file is populated with all headers
- Date: Mon, 17 May 2021 04:38:11 +0000 (UTC)
commit 67a9563a133eb2bafccfacd1a96f18f49c8de03c
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date: Thu May 13 14:00:54 2021 +0200
test: Add a CI job that ensures that PCH file is populated with all headers
...And the other way around, so that we won't include more than needed
both in code and pch headers
As per this we need to install actual bash and grep on alpine as this
script needs those features (which are not provided by buysbox).
.gitlab-ci.yml | 29 ++++++++-
test/check-pch.sh | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 214 insertions(+), 2 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 5a9c2308..e1788ee3 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -14,7 +14,7 @@ stages:
.gjs-alpine:
variables:
- FDO_DISTRIBUTION_TAG: '2021-04-02.0'
+ FDO_DISTRIBUTION_TAG: '2021-05-13.0'
FDO_UPSTREAM_REPO: GNOME/gjs
build-alpine-image:
@@ -23,7 +23,7 @@ build-alpine-image:
- .gjs-alpine
stage: prepare
variables:
- FDO_DISTRIBUTION_PACKAGES: cppcheck git python3 yarn
+ FDO_DISTRIBUTION_PACKAGES: cppcheck git python3 yarn bash grep
FDO_DISTRIBUTION_EXEC: |
python3 -m ensurepip &&
rm -r /usr/lib/python*/ensurepip &&
@@ -199,6 +199,7 @@ cppcheck:
- '**/*.c'
- '**/*.cpp'
- '**/*.h'
+ - '**/*.hh'
cpplint:
when: on_success
@@ -221,6 +222,7 @@ cpplint:
- '**/*.c'
- '**/*.cpp'
- '**/*.h'
+ - '**/*.hh'
eslint:
when: on_success
@@ -243,6 +245,29 @@ eslint:
- .eslintrc.yml
- '**/.eslintrc.yml'
+pch_check:
+ when: on_success
+ stage: source_check
+ extends:
+ - .fdo.distribution-image@alpine
+ - .gjs-alpine
+ script:
+ - env SELFTEST=1 test/check-pch.sh
+ - test/check-pch.sh
+ except:
+ refs:
+ - schedules
+ - tags
+ variables:
+ - $CI_COMMIT_MESSAGE =~ /\[skip pch_check\]/
+ only:
+ changes:
+ - test/check-pch.sh
+ - '**/*.c'
+ - '**/*.cpp'
+ - '**/*.h'
+ - '**/*.hh'
+
iwyu:
when: on_success
stage: source_check
diff --git a/test/check-pch.sh b/test/check-pch.sh
new file mode 100755
index 00000000..fd27b10f
--- /dev/null
+++ b/test/check-pch.sh
@@ -0,0 +1,187 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: LGPL-2.0-or-later
+# SPDX-FileCopyrightText: 2021 Marco Trevisan <marco trevisan canonical com>
+set -e
+
+if [ -n "$SELFTEST" ]; then
+ unset SELFTEST
+ set -x
+ self="$(realpath "$0")"
+ test_paths=()
+ trap 'rm -rf -- "${test_paths[@]}"' EXIT
+
+ test_env() {
+ local code_path="$(mktemp -t -d "check-pch-XXXXXX")"
+ test_paths+=("$code_path")
+ cd "$code_path"
+ mkdir gjs gi
+ echo "#include <stlib.h>" >> gjs/gjs_pch.hh
+ }
+
+ expect_success() {
+ "$self" || exit 1
+ }
+ expect_failure() {
+ "$self" && exit 1 || true
+ }
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ expect_success
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "#include <stdio.h>" >> gi/code.c
+ expect_failure
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "#include <invalid1.h>" >> gi/code1.cpp
+ echo "#include <invalid2.h>" >> gi/code1.c
+ expect_failure
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "#include <invalid.h> // check-pch: ignore" >> gi/other-code.c
+ expect_success
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "#include <invalid1.h> // NOcheck-pch: ignore" >> gi/code.c
+ echo "#include <invalid2.h> // check-pch: ignoreNO" >> gi/code.c
+ echo "#include <invalid3.h> // check-pch: ignore, yes" >> gi/other-code.c
+ expect_failure
+
+ test_env
+ echo "#include <invalid.h>" >> gjs/gjs_pch.hh
+ echo "#include <stlib.h>" >> gi/code.c
+ expect_failure
+
+ test_env
+ echo "#include <invalid.h> // check-pch: ignore, yes" >> gjs/gjs_pch.hh
+ echo "#include <stlib.h>" >> gi/code.c
+ expect_success
+
+ test_env
+ echo "#include <invalid.h>" >> gi/ignored-file.hh
+ echo "#include <stlib.h>" >> gi/code.c
+ expect_success
+
+ test_env
+ echo '# include <stlib.h>' >> gi/code.c
+ echo '# include "local/header.h"' >> gi/code.c
+ expect_success
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo '#include "local/header.h"' >> gjs/gjs_pch.hh
+ expect_failure
+
+ test_env
+ echo "# include <stlib.h>" >> gi/code.c
+ echo "# include <other/include.h>" >> gi/code.c
+ echo " # include <other/include.h>" >> gi/other-file.c
+ echo "# include <other/include.h>" >> gjs/gjs_pch.hh
+ expect_success
+
+ test_env
+ echo "# include <stlib.h>" >> gi/code.c
+ echo "# include <invalid.h>/*comment*/" >> gi/invalid-file.c
+ expect_failure
+
+ test_env
+ echo "# include <stlib.h>" >> gi/code.c
+ echo " # include <other/include.h>" >> gi/other-file.c
+ expect_failure
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "//#include <invalid.h>" >> gi/invalid-file.c
+ echo "// #include <invalid.h>" >> gi/invalid-file.c
+ echo "//#include <invalid.h>" >> gjs/gjs_pch.hh
+ expect_success
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "/*comment*/#include <invalid.h>/*comment*/" >> gi/invalid-file.c
+ # This is not supported: expect_failure
+
+ test_env
+ echo "#include <stlib.h>" >> gi/code.c
+ echo "# /*FIXME */ include /*Why should you do it?*/ <invalid.h>" >> gi/invalid-file.c
+ # This is not supported: expect_failure
+
+ exit 0
+fi
+
+PCH_FILES=(gjs/gjs_pch.hh)
+IGNORE_COMMENT="check-pch: ignore"
+
+CODE_PATHS=(gjs gi)
+INCLUDED_FILES=(
+ \*.c
+ \*.cpp
+ \*.h
+)
+
+grep_include_lines() {
+ grep -h '^\s*#\s*include\s*[<"][^>"]\+[>"]' "$@" | uniq
+}
+
+grep_header_file() {
+ local header_file="${1//./\\.}"
+ shift
+ grep -qs "^\s*#\s*include\s*[<\"]${header_file}[>\"]" "$@"
+}
+
+# List all the included headers
+mapfile -t includes < <(grep_include_lines \
+ -r \
+ $(printf -- "--include %s\n" "${INCLUDED_FILES[@]}") \
+ "${CODE_PATHS[@]}" \
+ | grep -vw "$IGNORE_COMMENT")
+
+missing=()
+for h in "${includes[@]}"; do
+ if [[ "$h" =~ \#[[:space:]]*include[[:space:]]*\<([^\>]+)\> ]]; then
+ header_file="${BASH_REMATCH[1]}"
+ if ! grep_header_file "$header_file" "${PCH_FILES[@]}"; then
+ echo "Header <$header_file> not added to PCH file"
+ missing+=("$header_file")
+ fi
+ fi
+done
+
+if [ "${#missing[@]}" -gt 0 ]; then
+ echo
+ echo "Headers not added to the PCH file found, please add to ${PCH_FILES[*]}"
+ echo "Otherwise you can ignore them with a leading comment such as"
+ echo " #include <${missing[0]}> // $IGNORE_COMMENT"
+ exit 1
+fi
+
+# And now, the other way around...
+mapfile -t pch_includes < <(grep_include_lines \
+ "${PCH_FILES[@]}" \
+ | grep -vw "$IGNORE_COMMENT")
+
+unneeded=()
+for h in "${pch_includes[@]}"; do
+ if [[ "$h" =~ \#[[:space:]]*include[[:space:]]*[\<\"]([^\>\"]+)[\>\"] ]]; then
+ header_file="${BASH_REMATCH[1]}"
+ if ! grep_header_file "$header_file" -r \
+ $(printf -- "--include %s\n" "${INCLUDED_FILES[@]}") \
+ "${CODE_PATHS[@]}"; then
+ echo "Header <$header_file> included in one PCH is not used in code"
+ unneeded+=("$header_file")
+ fi
+ fi
+done
+
+if [ "${#unneeded[@]}" -gt 0 ]; then
+ echo
+ echo "Unneeded headers added to the PCH file found, remove from ${PCH_FILES[*]}"
+ echo "Otherwise you can ignore them with a leading comment such as"
+ echo " #include <${unneeded[0]}> // $IGNORE_COMMENT"
+ exit 1
+fi
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]