Created
January 10, 2026 13:29
-
-
Save aengelke/82b9919222dbc2c43fcfc5bb79dceee6 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/sh | |
| # SPDX-FileCopyrightText: 2025 Alexis Engelke | |
| # SPDX-License-Identifier: Apache-2.0 | |
| USE_GCC=OFF | |
| DISABLE_PCH=OFF | |
| set -euo pipefail | |
| cat >CMakeLists.txt <<EOF | |
| cmake_minimum_required(VERSION 3.31) | |
| project(test) | |
| add_compile_definitions(M_CMD=\${M_CMD}) | |
| add_executable(test test.c) | |
| target_precompile_headers(test PRIVATE test.h) | |
| EOF | |
| cat >test.c <<EOF | |
| #include <stdio.h> | |
| #include "test.h" | |
| #if M_HDR == 2 | |
| #define M_SRC 20 | |
| #else | |
| #define M_SRC 10 | |
| #endif | |
| int main(void) { | |
| printf("%d %d %d\n", M_HDR, M_SRC, hdrfn()); | |
| return 0; | |
| } | |
| EOF | |
| cat >test.h <<EOF | |
| #ifndef TEST_H | |
| #define TEST_H | |
| #define M_HDR 2 | |
| static inline int hdrfn() { | |
| return M_CMD; | |
| } | |
| #endif | |
| EOF | |
| if [ $USE_GCC == "ON" ]; then | |
| export CC=gcc | |
| export CFLAGS="-fpch-preprocess" | |
| else | |
| export CC=clang | |
| export CFLAGS="-Xclang -fno-pch-timestamp" | |
| fi | |
| rm -rf build cache | |
| export CCACHE_DIR=$PWD/cache | |
| cmake -G Ninja -S . -B build -DCMAKE_C_COMPILER_LAUNCHER=ccache \ | |
| -DM_CMD=5 -DCMAKE_DISABLE_PRECOMPILE_HEADERS=$DISABLE_PCH | |
| build_test() { # build_test <expected output> <expected cache stats> | |
| CCACHE_SLOPPINESS=pch_defines,time_macros CCACHE_DEBUG=1 ninja -v -C build | |
| output=`./build/test` | |
| ninja -C build -t clean | |
| stats=`ccache --print-stats | awk '/^direct_cache_hit/{dch=$2}/^preprocessed_cache_hit/{pch=$2}/cache_miss/{cm=$2}END{print dch,pch,cm}'` | |
| if [ $DISABLE_PCH == "OFF" ] && [ "x$stats" != "x$2" ]; then | |
| echo "wrong stats: $stats != $2" | |
| ccache -svv | |
| fi | |
| if [ "x$output" != "x$1" ]; then echo "wrong result: $output != $1"; exit 1; fi | |
| ccache -z >/dev/null | |
| } | |
| # Test 1: initial build, no hits | |
| build_test "2 20 5" "0 0 2" | |
| # Test 2: change header, no hits | |
| sed -i "s/M_HDR 2/M_HDR 1/" test.h | |
| build_test "1 10 5" "0 0 2" | |
| # Test 3: change header back, hit for pch and test.c | |
| sed -i "s/M_HDR 1/M_HDR 2/" test.h | |
| build_test "2 20 5" "2 0 0" | |
| # Test 4: change header forth again, hit for pch and test.c | |
| sed -i "s/M_HDR 2/M_HDR 1/" test.h | |
| build_test "1 10 5" "2 0 0" | |
| # Test 5: change cmdline macro definition, no hits | |
| cmake -B build -DM_CMD=32 | |
| build_test "1 10 32" "0 0 2" | |
| # Test 6: change cmdline macro definition back, hit for pch and test.c | |
| cmake -B build -DM_CMD=5 | |
| build_test "1 10 5" "2 0 0" | |
| # Test 7: change cmdline macro definition forth and change test.h at the same time, no hits | |
| cmake -B build -DM_CMD=32 | |
| sed -i "s/M_HDR 1/M_HDR 2/" test.h | |
| build_test "2 20 32" "0 0 2" | |
| # Test 8: whitespace change to source file. PCH is hit test.c is direct miss but preprocessed hit | |
| echo "/* new comment*/" >>test.c | |
| build_test "2 20 32" "1 1 0" | |
| # Test 9: whitespace change to header. PCH will be missed, hence source file will be recompiled | |
| echo "/* new comment*/" >>test.h | |
| build_test "2 20 32" "0 0 2" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment