#!/bin/sh set -eu base="${TMPDIR-/tmp}/mcpu-cpp-dependency-targets-$$" mkdir -p "$base" trap 'rm -rf "$base"' EXIT HUP INT TERM cd "$base" cat > main.c <<'EOT' #include "local.h" int main_value; EOT cat > local.h <<'EOT' #define LOCAL_VALUE 1 EOT # The established default target remains make-quoted and uses the configured # object suffix only when no explicit -MT/-MQ target is present. "$MCPU_CPP" --no-config -M main.c > default.d grep '^main\.o: main\.c \./local\.h$' default.d >/dev/null "$MCPU_CPP" --no-config --object-suffix .obj -M main.c > suffix.d grep '^main\.obj: main\.c \./local\.h$' suffix.d >/dev/null # -MT replaces the default target and is emitted exactly as supplied. "$MCPU_CPP" --no-config -M -MT build/main.o main.c > mt.d grep '^build/main\.o: main\.c \./local\.h$' mt.d >/dev/null "$MCPU_CPP" --no-config -M -MTattached.o main.c > mt-attached.d grep '^attached\.o: main\.c \./local\.h$' mt-attached.d >/dev/null "$MCPU_CPP" --no-config -M -MT 'raw one raw#two$' main.c > mt-raw.d grep '^raw one raw#two\$: main\.c \./local\.h$' mt-raw.d >/dev/null # -MQ applies Make quoting to the target. "$MCPU_CPP" --no-config -M -MQ '$(OBJDIR)/main.o' main.c > mq.d grep '^\$\$(OBJDIR)/main\.o: main\.c \./local\.h$' mq.d >/dev/null "$MCPU_CPP" --no-config -M '-MQ$(OBJDIR)/attached.o' main.c > mq-attached.d grep '^\$\$(OBJDIR)/attached\.o: main\.c \./local\.h$' mq-attached.d >/dev/null "$MCPU_CPP" --no-config -M -MQ 'dir name/#x$.o' main.c > mq-special.d grep '^dir\\ name/\\#x\$\$\.o: main\.c \./local\.h$' mq-special.d >/dev/null "$MCPU_CPP" --no-config -M -MQ 'path\name.o' main.c > mq-backslash.d grep -F 'path\name.o: main.c ./local.h' mq-backslash.d >/dev/null # Multiple targets produce one rule. As in GNU CPP, all -MT targets precede # all -MQ targets; command-line order is preserved inside each class. "$MCPU_CPP" --no-config -M \ -MQ '$(DIR)/quoted1.o' \ -MT raw1.o \ -MQ 'quoted two.o' \ -MT 'raw2.o raw3.o' \ main.c > multiple.d grep '^raw1\.o raw2\.o raw3\.o \$\$(DIR)/quoted1\.o quoted\\ two\.o: main\.c \./local\.h$' multiple.d >/dev/null # Explicit targets override the automatic target even when an object suffix was # requested. "$MCPU_CPP" --no-config --object-suffix .obj -M -MT explicit.target main.c > explicit.d grep '^explicit\.target: main\.c \./local\.h$' explicit.d >/dev/null # -MT/-MQ work in side-effect dependency modes and with -MF. "$MCPU_CPP" --no-config -MD -MF md.d -MT md-target.o main.c > md.i grep '^md-target\.o: main\.c \./local\.h$' md.d >/dev/null grep '^int main_value;$' md.i >/dev/null "$MCPU_CPP" --no-config -MMD -MF mmd.d -MQ '$(OUT)/mmd.o' main.c > mmd.i grep '^\$\$(OUT)/mmd\.o: main\.c \./local\.h$' mmd.d >/dev/null grep '^int main_value;$' mmd.i >/dev/null # Both options require an active dependency-generation mode. if "$MCPU_CPP" --no-config -MT orphan.o main.c > orphan.out 2> orphan.err; then echo "-MT without dependency generation unexpectedly succeeded" >&2 exit 1 fi grep -- '-MT/-MQ require one of -M, -MM, -MD or -MMD' orphan.err >/dev/null if "$MCPU_CPP" --no-config -MQ orphan.o main.c > orphan-q.out 2> orphan-q.err; then echo "-MQ without dependency generation unexpectedly succeeded" >&2 exit 1 fi grep -- '-MT/-MQ require one of -M, -MM, -MD or -MMD' orphan-q.err >/dev/null # Missing arguments remain command-line errors. if "$MCPU_CPP" --no-config -M -MT > missing-mt.out 2> missing-mt.err; then echo "-MT without an argument unexpectedly succeeded" >&2 exit 1 fi grep "argument missing after '-MT'" missing-mt.err >/dev/null if "$MCPU_CPP" --no-config -M -MQ > missing-mq.out 2> missing-mq.err; then echo "-MQ without an argument unexpectedly succeeded" >&2 exit 1 fi grep "argument missing after '-MQ'" missing-mq.err >/dev/null # Public help documents both options. "$MCPU_CPP" --help > help.out grep '^ -MT TARGET set unquoted make dependency target$' help.out >/dev/null grep '^ -MQ TARGET set make-quoted dependency target$' help.out >/dev/null