1#! /bin/bash 2# Copyright (C) Sebastian Pipping <sebastian@pipping.org> 3# Licensed under the MIT license 4 5export PS4='# ' 6 7 8_get_source_dir() { 9 echo "source__${version}" 10} 11 12 13_get_build_dir() { 14 local libbsd_part= 15 if ${with_libbsd}; then 16 libbsd_part=__libbsd 17 fi 18 19 local mingw_part= 20 if ${with_mingw}; then 21 mingw_part=__windows 22 fi 23 24 local char_part= 25 if ${with_unsigned_char}; then 26 char_part=__unsigned_char 27 fi 28 29 echo "build__${version}__unicode_${unicode_enabled}__xml_context_${xml_context}${libbsd_part}${mingw_part}${char_part}" 30} 31 32 33_get_coverage_dir() { 34 echo "coverage__${version}" 35} 36 37 38_configure() { 39 local configure_args=() 40 41 ${unicode_enabled} \ 42 && configure_args+=( CPPFLAGS='-DXML_UNICODE -DXML_UNICODE_WCHAR_T' ) 43 44 if [[ ${xml_context} -eq 0 ]]; then 45 configure_args+=( --disable-xml-context ) 46 else 47 configure_args+=( --enable-xml-context=${xml_context} ) 48 fi 49 50 ${with_libbsd} && configure_args+=( --with-libbsd ) 51 ${with_mingw} && configure_args+=( --host=i686-w64-mingw32 ) 52 53 ( 54 set -x 55 ./buildconf.sh &> configure.log 56 ./configure "${configure_args[@]}" "$@" &>> configure.log 57 ) 58} 59 60 61_copy_to() { 62 local target_dir="$1" 63 [[ -d "${target_dir}" ]] && return 0 64 65 mkdir "${target_dir}" 66 git archive --format=tar "${version}" | ( cd "${target_dir}" && tar x ) 67} 68 69 70_copy_missing_mingw_libaries() { 71 # These extra files are copied because 72 # * coverage GCC flags make them needed 73 # * With WINEDLLPATH Wine looks for .dll.so in these folders, not .dll 74 local target="$1" 75 local mingw_gcc_dll_dir="$(dirname "$(ls -1 /usr/lib*/gcc/i686-w64-mingw32/*/libgcc_s_sjlj-1.dll | head -n1)")" 76 for dll in libgcc_s_sjlj-1.dll libstdc++-6.dll; do 77 ( 78 set -x 79 ln -s "${mingw_gcc_dll_dir}"/${dll} "${target}"/${dll} 80 ) 81 done 82 83 local mingw_pthread_dll_dir="$(dirname "$(ls -1 /usr/i686-w64-mingw32/lib*/libwinpthread-1.dll | head -n1)")" 84 for dll in libwinpthread-1.dll; do 85 source="${mingw_pthread_dll_dir}"/${dll} 86 [[ -e "${source}" ]] || continue 87 ( 88 set -x 89 ln -s "${source}" "${target}"/${dll} 90 ) 91 done 92} 93 94 95_run() { 96 local source_dir="$1" 97 local build_dir="$2" 98 local capture_dir=lib 99 100 local BASE_FLAGS='-pipe -Wall -Wextra -pedantic -Wno-overlength-strings' 101 BASE_FLAGS+=' --coverage --no-inline' 102 103 ${with_unsigned_char} && BASE_FLAGS="${BASE_FLAGS} -funsigned-char" 104 105 local CFLAGS="-std=c99 ${BASE_FLAGS}" 106 local CXXFLAGS="-std=c++98 ${BASE_FLAGS}" 107 108 ( 109 set -e 110 cd "${build_dir}" 111 112 _configure \ 113 CFLAGS="${BASE_FLAGS}" \ 114 CXXFLAGS="${BASE_FLAGS}" 115 116 ( 117 set -x 118 make -C lib &> build.log 119 120 lcov -c -d "${capture_dir}" -i -o "${coverage_info}-zero" &> run.log 121 ) 122 123 if ${with_mingw}; then 124 for d in {tests,xmlwf}/.libs ; do 125 mkdir -p "${d}" 126 _copy_missing_mingw_libaries "${d}" 127 done 128 fi 129 130 set -x 131 make all check run-xmltest 132 133 lcov -c -d "${capture_dir}" -o "${coverage_info}-test" &>> run.log 134 lcov \ 135 -a "${coverage_info}-zero" \ 136 -a "${coverage_info}-test" \ 137 -o "${coverage_info}-all" \ 138 &>> run.log 139 140 # Make sure that files overlap in report despite different build folders 141 sed "/SF:/ s,${build_dir}/,${source_dir}/," "${coverage_info}-all" > "${coverage_info}" 142 ) |& sed 's,^, ,' 143 res=${PIPESTATUS[0]} 144 145 if [[ ${res} -eq 0 ]]; then 146 echo PASSED 147 else 148 echo FAILED >&2 149 return 1 150 fi 151} 152 153 154_merge_coverage_info() { 155 local coverage_dir="$1" 156 shift 157 local build_dirs=( "$@" ) 158 159 mkdir -p "${coverage_dir}" 160 ( 161 local lcov_merge_args=() 162 for build_dir in "${build_dirs[@]}"; do 163 lcov_merge_args+=( -a "${build_dir}/${coverage_info}" ) 164 done 165 lcov_merge_args+=( -o "${coverage_dir}/${coverage_info}" ) 166 167 set -x 168 lcov "${lcov_merge_args[@]}" 169 ) &> "${coverage_dir}/merge.log" 170} 171 172 173_render_html_report() { 174 local coverage_dir="$1" 175 genhtml -o "${coverage_dir}" "${coverage_dir}/${coverage_info}" &> "${coverage_dir}/render.log" 176} 177 178 179_show_summary() { 180 local coverage_dir="$1" 181 lcov -q -l "${coverage_dir}/${coverage_info}" | grep -v '^\[' 182} 183 184 185_main() { 186 version="$(git describe --tags)" 187 coverage_info=coverage.info 188 189 local build_dirs=() 190 local source_dir="$(_get_source_dir)" 191 local coverage_dir="$(_get_coverage_dir)" 192 193 _copy_to "${source_dir}" 194 195 _build_case() { 196 local build_dir="$(_get_build_dir)" 197 198 echo "[${build_dir}]" 199 _copy_to "${build_dir}" 200 _run "${source_dir}" "${build_dir}" 201 202 build_dirs+=( "${build_dir}" ) 203 } 204 205 # All combinations: 206 with_unsigned_char=false 207 with_libbsd=false 208 for with_mingw in true false ; do 209 for unicode_enabled in true false ; do 210 if ${unicode_enabled} && ! ${with_mingw} ; then 211 continue 212 fi 213 214 for xml_context in 0 1024 ; do 215 _build_case 216 done 217 done 218 done 219 220 # Single cases: 221 with_libbsd=true _build_case 222 with_unsigned_char=true _build_case 223 224 echo 225 echo 'Merging coverage files...' 226 _merge_coverage_info "${coverage_dir}" "${build_dirs[@]}" 227 228 echo 'Rendering HTML report...' 229 _render_html_report "${coverage_dir}" 230 echo "--> ${coverage_dir}/index.html" 231 232 echo 233 _show_summary "${coverage_dir}" 234} 235 236 237_main 238