#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-dep-side-effects-$$" mkdir -p "$base/src" "$base/user" "$base/sys" "$base/out" "$base/stdin" trap 'rm -rf "$base"' EXIT HUP INT TERM cat > "$base/src/main.c" <<'EOT' #include "user.h" #include MAIN_BODY EOT cat > "$base/user/user.h" <<'EOT' USER_BODY EOT cat > "$base/sys/system.h" <<'EOT' #include "system-child.h" SYSTEM_BODY EOT cat > "$base/sys/system-child.h" <<'EOT' SYSTEM_CHILD_BODY EOT # -MD keeps preprocessing output and writes basename.d in the current # directory when no -o/-MF is present. The input directory is not copied to # the default dependency filename. ( cd "$base" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MD "$base/src/main.c" > md.out ) test -s "$base/md.out" grep 'MAIN_BODY' "$base/md.out" >/dev/null test -s "$base/main.d" grep '^main\.o:' "$base/main.d" >/dev/null for f in "$base/src/main.c" "$base/user/user.h" \ "$base/sys/system.h" "$base/sys/system-child.h" do grep -F "$f" "$base/main.d" >/dev/null || { echo "-MD omitted dependency: $f" >&2 exit 1 } done # -MMD has the same side-effect behavior but applies the already established # -MM user-dependency filter. rm -f "$base/main.d" ( cd "$base" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MMD "$base/src/main.c" > mmd.out ) test -s "$base/mmd.out" grep 'MAIN_BODY' "$base/mmd.out" >/dev/null test -s "$base/main.d" grep -F "$base/src/main.c" "$base/main.d" >/dev/null grep -F "$base/user/user.h" "$base/main.d" >/dev/null ! grep -F "$base/sys/system.h" "$base/main.d" >/dev/null ! grep -F "$base/sys/system-child.h" "$base/main.d" >/dev/null # With ordinary -o, preprocessing goes to that file and the automatic # dependency filename is obtained by replacing its suffix with .d. rm -f "$base/main.d" "$base/out/result.i" "$base/out/result.d" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MD "$base/src/main.c" -o "$base/out/result.i" test -s "$base/out/result.i" grep 'MAIN_BODY' "$base/out/result.i" >/dev/null test -s "$base/out/result.d" grep '^main\.o:' "$base/out/result.d" >/dev/null test ! -e "$base/main.d" # -MF overrides automatic dependency naming while leaving normal preprocessing # output semantics untouched. rm -f "$base/custom.d" "$base/main.d" ( cd "$base" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MD -MF custom.d "$base/src/main.c" > mf.out ) test -s "$base/mf.out" grep 'MAIN_BODY' "$base/mf.out" >/dev/null test -s "$base/custom.d" test ! -e "$base/main.d" # Attached -MFfile spelling is accepted as by GNU cpp. rm -f "$base/attached.d" ( cd "$base" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MMD -MFattached.d "$base/src/main.c" > attached.out ) test -s "$base/attached.d" ! grep -F "$base/sys/system.h" "$base/attached.d" >/dev/null # -MF also redirects the already implemented dependency-only -M/-MM modes. rm -f "$base/only.d" "$base/only.out" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -M -MF "$base/only.d" "$base/src/main.c" > "$base/only.out" test ! -s "$base/only.out" test -s "$base/only.d" grep -F "$base/sys/system.h" "$base/only.d" >/dev/null rm -f "$base/only-user.d" "$base/only-user.out" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MM -MF "$base/only-user.d" "$base/src/main.c" > "$base/only-user.out" test ! -s "$base/only-user.out" test -s "$base/only-user.d" ! grep -F "$base/sys/system.h" "$base/only-user.d" >/dev/null # -MF - means dependency stdout. Put normal preprocessing in a regular -o # file so the two streams are easy to verify independently. rm -f "$base/out/stdout.i" "$base/out/stdout.d" "$MCPU_CPP" --no-config -I "$base/user" -isystem "$base/sys" \ -MMD -MF - "$base/src/main.c" -o "$base/out/stdout.i" \ > "$base/mf-dash.out" test -s "$base/out/stdout.i" grep 'MAIN_BODY' "$base/out/stdout.i" >/dev/null grep '^main\.o:' "$base/mf-dash.out" >/dev/null test ! -e "$base/out/stdout.d" # stdin follows the existing '-' target convention and gets '-.d' when -MD # needs an automatic dependency filename. ( cd "$base/stdin" printf 'STDIN_BODY\n' | "$MCPU_CPP" --no-config -MD > stdout.i ) test -s "$base/stdin/stdout.i" grep 'STDIN_BODY' "$base/stdin/stdout.i" >/dev/null test -s "$base/stdin/-.d" grep '^-: -$' "$base/stdin/-.d" >/dev/null # -MF alone is a command-line error: there is no dependency mode to redirect. if "$MCPU_CPP" --no-config -MF "$base/orphan.d" "$base/src/main.c" \ > /dev/null 2>&1; then echo "-MF without a dependency mode unexpectedly succeeded" >&2 exit 1 fi