Skip to content

Commit 6fcf436

Browse files
committed
New gcovr package 2026-06-15
1 parent 6a3ccfd commit 6fcf436

3 files changed

Lines changed: 314 additions & 1 deletion

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
test.txt
22
test2.txt
33
__pycache__
4+
/tmp/
45

scripts/lcov-jenkins-gcc-13.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ fi
101101

102102
# pip install --upgrade gcovr==8.6 || true
103103
# pip install --upgrade git+https://github.com/Spacetown/gcovr.git@05cbbc6f769da3671a3f659ad99198bac4d62dee || true
104-
pip install --upgrade git+https://github.com/gcovr/gcovr.git@8dc1762283bbc30044f12e998b78e7f762e0f849 || true
104+
# pip install --upgrade git+https://github.com/gcovr/gcovr.git@8dc1762283bbc30044f12e998b78e7f762e0f849 || true
105+
pip install --upgrade git+https://github.com/gcovr/gcovr.git@2c6adcb521e88149c9256002ff95de8853bd6573 || true
105106

106107
gcovr --version
107108

Lines changed: 311 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,311 @@
1+
#!/bin/bash
2+
3+
# See docs at https://github.com/cppalliance/ci-automation/blob/master/scripts/docs/README.md
4+
5+
set -e
6+
7+
scriptname="lcov-jenkins-gcc-13.sh"
8+
echo "Starting $scriptname"
9+
10+
# READ IN COMMAND-LINE OPTIONS
11+
12+
TEMP=$(getopt -o h:: --long help::,skip-gcovr::,skip-genhtml::,skip-diff-report::,only-gcovr:: -- "$@")
13+
eval set -- "$TEMP"
14+
15+
# extract options and their arguments into variables.
16+
while true ; do
17+
case "$1" in
18+
-h|--help)
19+
helpmessage="""
20+
usage: $scriptname [-h] [--skip-gcovr] [--skip-genhtml] [--skip-diff-report] [--only-gcovr]
21+
22+
Builds library documentation.
23+
24+
optional arguments:
25+
-h, --help Show this help message and exit
26+
--skip-gcovr Don't run gcovr
27+
--skip-genhtml Don't run genhtml
28+
--skip-diff-report Don't run the diff-report
29+
--only-gcovr Only run the main gcovr report, which is the same as multiple
30+
skip options.
31+
If the goal is to run gcovr, this is the preferred method
32+
since this flag can be modified to skip other steps later.
33+
"""
34+
35+
echo ""
36+
echo "$helpmessage" ;
37+
echo ""
38+
exit 0
39+
;;
40+
--skip-gcovr)
41+
skipgcovroption="yes" ; shift 2 ;;
42+
--skip-genhtml)
43+
skipgenhtmloption="yes" ; shift 2 ;;
44+
--skip-diff-report)
45+
skipdiffreportoption="yes" ; shift 2 ;;
46+
--only-gcovr)
47+
skipdiffreportoption="yes" ; skipgenhtmloption="yes" ; shift 2 ;;
48+
--) shift ; break ;;
49+
*) echo "Internal error!" ; exit 1 ;;
50+
esac
51+
done
52+
53+
timestamp=$(date +"%Y-%m-%d-%H-%M-%S")
54+
55+
env
56+
57+
if [ -z "${REPONAME}" ]; then
58+
echo "Please set the env variable REPONAME"
59+
exit 1
60+
fi
61+
62+
if [ -z "${ORGANIZATION}" ]; then
63+
echo "Please set the env variable ORGANIZATION"
64+
exit 1
65+
fi
66+
67+
if [ "${BOOST_BRANCH_COVERAGE}" = "0" ]; then
68+
export LCOV_BRANCH_COVERAGE=0
69+
export GCOVR_BRANCH_COVERAGE=0
70+
elif [ "${BOOST_BRANCH_COVERAGE}" = "1" ]; then
71+
export LCOV_BRANCH_COVERAGE=1
72+
export GCOVR_BRANCH_COVERAGE=1
73+
fi
74+
75+
# Default of GCOVR_BRANCH_COVERAGE is 0 -> no branch coverage report
76+
# That may be overwritten by BOOST_BRANCH_COVERAGE, above.
77+
: "${GCOVR_BRANCH_COVERAGE:=0}"
78+
79+
GCOVR_EXTRA_OPTIONS=()
80+
if [ "${GCOVR_BRANCH_COVERAGE}" = "0" ]; then
81+
GCOVR_EXTRA_OPTIONS=(--exclude-branches-by-pattern='.*')
82+
fi
83+
84+
# export USER=$(whoami)
85+
# echo "USER is ${USER}"
86+
87+
# these packages are already installed on containers.
88+
sudo apt-get update
89+
sudo apt-get install -y python3-pip sudo git curl jq
90+
91+
# codecov.sh installs perl packages also
92+
# sudo apt-get install -y libcapture-tiny-perl libdatetime-perl libdatetime-format-dateparse-perl
93+
sudo apt-get install -y libdatetime-format-dateparse-perl
94+
95+
# expecting a venv to already exist in /opt/venv.
96+
export pythonvirtenvpath=/opt/venv
97+
if [ -f ${pythonvirtenvpath}/bin/activate ]; then
98+
# shellcheck source=/dev/null
99+
source ${pythonvirtenvpath}/bin/activate
100+
fi
101+
102+
# pip install --upgrade gcovr==8.6 || true
103+
# pip install --upgrade git+https://github.com/Spacetown/gcovr.git@05cbbc6f769da3671a3f659ad99198bac4d62dee || true
104+
pip install --upgrade git+https://github.com/gcovr/gcovr.git@8dc1762283bbc30044f12e998b78e7f762e0f849 || true
105+
106+
gcovr --version
107+
108+
export B2_TOOLSET="gcc-13"
109+
export LCOV_VERSION="v2.3"
110+
export LCOV_OPTIONS="--ignore-errors mismatch"
111+
112+
export REPO_NAME=${ORGANIZATION}/${REPONAME}
113+
export PATH=~/.local/bin:/usr/local/bin:$PATH
114+
export BOOST_CI_CODECOV_IO_UPLOAD="skip"
115+
116+
# lcov will be present later
117+
export PATH=/tmp/lcov/bin:$PATH
118+
# command -v lcov
119+
# lcov --version
120+
121+
collect_coverage () {
122+
123+
git clone https://github.com/boostorg/boost-ci.git boost-ci-cloned --depth 1
124+
cp -prf boost-ci-cloned/ci .
125+
rm -rf boost-ci-cloned
126+
127+
SELF=$(basename "$REPO_NAME")
128+
export SELF
129+
BOOST_CI_SRC_FOLDER=$(pwd)
130+
export BOOST_CI_SRC_FOLDER
131+
132+
echo "In collect_coverage. Running common_install.sh"
133+
# shellcheck source=/dev/null
134+
. ./ci/common_install.sh
135+
136+
# Formatted such as "cppalliance/buffers cppalliance/http-proto"
137+
for EXTRA_LIB in ${EXTRA_BOOST_LIBRARIES}; do
138+
EXTRA_LIB_REPO=$(basename "$EXTRA_LIB")
139+
if [ ! -d "$BOOST_ROOT/libs/${EXTRA_LIB_REPO}" ]; then
140+
pushd "$BOOST_ROOT/libs"
141+
git clone "https://github.com/${EXTRA_LIB}" -b "$BOOST_BRANCH" --depth 1
142+
popd
143+
fi
144+
done
145+
146+
echo "In collect_coverage. Running codecov.sh"
147+
cd "$BOOST_ROOT/libs/$SELF"
148+
ci/travis/codecov.sh
149+
150+
cd "$BOOST_CI_SRC_FOLDER"
151+
152+
# lcov --ignore-errors unused --remove coverage.info -o coverage_filtered.info '*/test/*' '*/extra/*' '*/example/*'
153+
lcov --ignore-errors unused --extract coverage.info "*/boost/$SELF/*" "*/$SELF/src/*" -o coverage_filtered.info
154+
sed "s|${BOOST_ROOT}/boost/$SELF|${BOOST_ROOT}/libs/$SELF/include/boost/$SELF|g" coverage_filtered.info > coverage_remapped.info
155+
156+
}
157+
158+
collect_coverage
159+
160+
# Now the tracefile is coverage_filtered.info
161+
if [ ! "$skipgenhtmloption" = "yes" ]; then
162+
genhtml --show-navigation -o genhtml coverage_remapped.info
163+
fi
164+
165+
#########################
166+
#
167+
# gcovr
168+
#
169+
#########################
170+
171+
if [ ! "$skipgcovroption" = "yes" ]; then
172+
173+
GCOVRFILTER1=".*/boost/$SELF/.*"
174+
GCOVRFILTER2=".*/$SELF/src/.*"
175+
if [ -d "gcovr" ]; then
176+
rm -r gcovr
177+
fi
178+
mkdir gcovr
179+
cd ../boost-root
180+
if [ ! -d ci-automation ]; then
181+
git clone -b master https://github.com/cppalliance/ci-automation
182+
cd ci-automation
183+
git branch -vv || true
184+
cd ..
185+
else
186+
cd ci-automation
187+
git pull || true
188+
git branch -vv || true
189+
cd ..
190+
fi
191+
192+
outputlocation="$BOOST_CI_SRC_FOLDER/gcovr"
193+
194+
# First pass, output json
195+
gcovr "${GCOVR_EXTRA_OPTIONS[@]}" --merge-mode-functions separate --sort uncovered-percent --html-title "$REPONAME" --merge-lines --exclude-unreachable-branches --exclude-throw-branches --exclude '.*/test/.*' --exclude '.*/extra/.*' --exclude '.*/example/.*' --exclude '.*/examples/.*' --filter "$GCOVRFILTER1" --filter "$GCOVRFILTER2" --html --output "${outputlocation}/index.html" --json-summary-pretty --json-summary "${outputlocation}/summary.json" --json "${outputlocation}/coverage-raw.json"
196+
197+
# Fix paths
198+
python3 "ci-automation/scripts/fix_paths.py" \
199+
"$outputlocation/coverage-raw.json" \
200+
"$outputlocation/coverage-fixed.json" \
201+
--repo "$REPONAME"
202+
203+
# Create symlinks so gcovr can find source files at repo-relative paths
204+
ln -sfn "$BOOST_CI_SRC_FOLDER/include" "$(pwd)/include" 2>/dev/null || true
205+
ln -sfn "$BOOST_CI_SRC_FOLDER/src" "$(pwd)/src" 2>/dev/null || true
206+
207+
# Second pass, generate html
208+
gcovr "${GCOVR_EXTRA_OPTIONS[@]}" -a "$outputlocation/coverage-fixed.json" \
209+
--merge-mode-functions separate \
210+
--merge-lines \
211+
--html-nested \
212+
--no-html-self-contained \
213+
--html-template-dir=ci-automation/gcovr-templates/html \
214+
--html-title "$REPONAME" \
215+
--html \
216+
--output "$outputlocation/index.html" \
217+
--json-summary-pretty \
218+
--json-summary "$outputlocation/summary.json"
219+
220+
# Second pass, generate html
221+
# Let's remove many options/flags from the second pass. See above.
222+
# gcovr "${GCOVR_EXTRA_OPTIONS[@]}" -a "$outputlocation/coverage-fixed.json" --merge-mode-functions separate --sort uncovered-percent --html-nested --html-template-dir=ci-automation/gcovr-templates/html --html-title "$REPONAME" --merge-lines --exclude-unreachable-branches --exclude-throw-branches --exclude '.*/test/.*' --exclude '.*/extra/.*' --exclude '.*/example/.*' --exclude '.*/examples/.*' --html --output "${outputlocation}/index.html" --json-summary-pretty --json-summary "$outputlocation/summary.json"
223+
224+
ls -al "${outputlocation}"
225+
226+
# Copy font files to output directory
227+
cp ci-automation/gcovr-templates/html/*.woff2 "$outputlocation/"
228+
229+
# Generate tree.json for sidebar navigation
230+
python3 "ci-automation/scripts/gcovr_build_tree.py" "${outputlocation}"
231+
232+
# Generate coverage badges
233+
python3 "ci-automation/scripts/generate_badges.py" "$outputlocation" --json "$outputlocation/summary.json"
234+
235+
fi
236+
237+
#########################################################################
238+
#
239+
# The following section is to generate a diff-report
240+
#
241+
#########################################################################
242+
243+
if [ ! "$skipdiffreportoption" = "yes" ]; then
244+
245+
#########################
246+
#
247+
# Collect coverage again the same way on the target branch, usually develop
248+
#
249+
#########################
250+
251+
# preparation:
252+
253+
# "$CHANGE_TARGET" is a variable from multibranch-pipeline.
254+
TARGET_BRANCH="${CHANGE_TARGET:-develop}"
255+
256+
cd "$BOOST_CI_SRC_FOLDER"
257+
BOOST_CI_SRC_FOLDER_ORIG=$BOOST_CI_SRC_FOLDER
258+
rm -rf ../boost-root
259+
cd ..
260+
# It was possible to have the new folder be named $SELF.
261+
# But just to be extra careful, choose another name such as
262+
ADIRNAME=${SELF}-target-branch-iteration
263+
if [ -d "$ADIRNAME" ]; then
264+
mv "$ADIRNAME" "$ADIRNAME.bck.$timestamp"
265+
fi
266+
git clone -b "$TARGET_BRANCH" "https://github.com/$ORGANIZATION/$SELF" "$ADIRNAME"
267+
cd "$ADIRNAME"
268+
# The "new" BOOST_CI_SRC_FOLDER:
269+
BOOST_CI_SRC_FOLDER=$(pwd)
270+
export BOOST_CI_SRC_FOLDER
271+
BOOST_CI_SRC_FOLDER_TARGET=$(pwd)
272+
export BOOST_CI_SRC_FOLDER_TARGET
273+
274+
# done with prep, now everything is the same as before
275+
276+
collect_coverage
277+
278+
# diff coverage report generation
279+
280+
BOOST_CI_SRC_FOLDER=$BOOST_CI_SRC_FOLDER_ORIG
281+
cd "$BOOST_CI_SRC_FOLDER/.."
282+
283+
if [ ! -d diff-coverage-report ]; then
284+
git clone https://github.com/grisumbras/diff-coverage-report
285+
else
286+
cd diff-coverage-report
287+
git pull || true
288+
cd ..
289+
fi
290+
291+
diff -Nru0 --minimal -x '.git' -x '*.info' -x genhtml -x gcovr -x diff-report \
292+
"$BOOST_CI_SRC_FOLDER_TARGET" "$BOOST_CI_SRC_FOLDER_ORIG" | tee difference
293+
294+
diff-coverage-report/diff-coverage-report.py -D difference \
295+
-O "$BOOST_CI_SRC_FOLDER/diff-report" \
296+
-B "$BOOST_CI_SRC_FOLDER_TARGET/coverage_filtered.info" \
297+
-T "$BOOST_CI_SRC_FOLDER_ORIG/coverage_filtered.info" \
298+
-S "$BOOST_CI_SRC_FOLDER_ORIG" \
299+
-P "$BOOST_CI_SRC_FOLDER_TARGET" "$BOOST_CI_SRC_FOLDER_ORIG" \
300+
"$BOOST_ROOT/libs/$SELF" "$BOOST_CI_SRC_FOLDER_ORIG" \
301+
"$BOOST_ROOT/boost" "$BOOST_CI_SRC_FOLDER_ORIG/include/boost"
302+
303+
# In the event that diff-coverage-report.py doesn't run, ensure
304+
# an empty directory exists anyway to upload to S3.
305+
mkdir -p "$BOOST_CI_SRC_FOLDER/diff-report"
306+
touch "$BOOST_CI_SRC_FOLDER/diff-report/test.txt"
307+
308+
# Done, return everything back.
309+
cd "$BOOST_CI_SRC_FOLDER"
310+
311+
fi

0 commit comments

Comments
 (0)