| 1 | # Proof-of-concept for bjam-based testing mechanism. This file should |
|---|
| 2 | # work on NT, Cygwin, and Linux. No promises for other platforms. |
|---|
| 3 | |
|---|
| 4 | # Set a variable which says how to dump a file to stdout |
|---|
| 5 | if $(NT) |
|---|
| 6 | { |
|---|
| 7 | CATENATE = type ; |
|---|
| 8 | } |
|---|
| 9 | else |
|---|
| 10 | { |
|---|
| 11 | CATENATE = cat ; |
|---|
| 12 | } |
|---|
| 13 | |
|---|
| 14 | # invoke the given action rule `act' to build target from sources |
|---|
| 15 | rule do-make ( target : sources * : act ) |
|---|
| 16 | { |
|---|
| 17 | DEPENDS $(target) : $(sources) ; |
|---|
| 18 | $(act) $(target) : $(sources) ; |
|---|
| 19 | } |
|---|
| 20 | |
|---|
| 21 | # top-level version of do-make which causes target to be built by |
|---|
| 22 | # default |
|---|
| 23 | rule make ( target : sources * : act ) |
|---|
| 24 | { |
|---|
| 25 | DEPENDS all : $(target) ; |
|---|
| 26 | do-make $(target) : $(sources) : $(act) ; |
|---|
| 27 | } |
|---|
| 28 | |
|---|
| 29 | # cause `target' to exist and building to succeed if invoking |
|---|
| 30 | # |
|---|
| 31 | # $(act) $(target) : $(sources) |
|---|
| 32 | # |
|---|
| 33 | # fails, and to fail if the action succeeds. |
|---|
| 34 | rule make-fail ( target : sources * : act ) |
|---|
| 35 | { |
|---|
| 36 | # Establish another logical target which refers to the same file, |
|---|
| 37 | # by using different grist. |
|---|
| 38 | DEPENDS all : <different-grist>$(target) ; |
|---|
| 39 | |
|---|
| 40 | # Make the new logical target depend on the target |
|---|
| 41 | DEPENDS <different-grist>$(target) : $(target) ; |
|---|
| 42 | |
|---|
| 43 | # Cause the target to be built from sources using $(act). |
|---|
| 44 | do-make $(target) : $(sources) : $(act) ; |
|---|
| 45 | |
|---|
| 46 | # Note that we expect target to fail to build |
|---|
| 47 | FAIL_EXPECTED $(target) ; |
|---|
| 48 | |
|---|
| 49 | # Build a failure marker file. Because targets are only built if |
|---|
| 50 | # all their dependents "succeed", the marker will only be |
|---|
| 51 | # generated if $(target) failed to build, as expected. |
|---|
| 52 | failure-marker <different-grist>$(target) ; |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | # Simple action rules which write text into the target. Different |
|---|
| 56 | # names for different purposes. |
|---|
| 57 | actions failure-marker |
|---|
| 58 | { |
|---|
| 59 | echo failed as expected > $(<) |
|---|
| 60 | } |
|---|
| 61 | |
|---|
| 62 | actions create |
|---|
| 63 | { |
|---|
| 64 | echo creating > $(<) |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | # An action which will always fail, for testing expected failure rules |
|---|
| 68 | actions fail-to-create |
|---|
| 69 | { |
|---|
| 70 | exit 1 |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | # Basic rule-action pair which builds the target by executing the |
|---|
| 74 | # given commands |
|---|
| 75 | rule do-run ( target : commands + ) |
|---|
| 76 | { |
|---|
| 77 | COMMANDS on $(target) = $(commands) ; |
|---|
| 78 | NOTFILE $(commands) ; |
|---|
| 79 | } |
|---|
| 80 | |
|---|
| 81 | # Run commands, leaving the output behind in $(<:S=.out). Echo to |
|---|
| 82 | # stdout if the command fails. |
|---|
| 83 | # |
|---|
| 84 | # Detailed explanation: |
|---|
| 85 | # |
|---|
| 86 | # $(COMMANDS) Run commands |
|---|
| 87 | # > $(<:S=.out) into the output file |
|---|
| 88 | # 2>&1 including stderr |
|---|
| 89 | # && and if that succeeds |
|---|
| 90 | # cp -f $(<:S=.out) $(<) copy the output file into the target |
|---|
| 91 | # || otherwise |
|---|
| 92 | # ( $(CATENATE) $(<:S=.out) dump any output to stdout |
|---|
| 93 | # && exit 1 and exit with an error code |
|---|
| 94 | # ) |
|---|
| 95 | actions do-run |
|---|
| 96 | { |
|---|
| 97 | $(COMMANDS) > $(<:S=.out) 2>&1 && cp -f $(<:S=.out) $(<) || ( $(CATENATE) $(<:S=.out) && exit 1 ) |
|---|
| 98 | } |
|---|
| 99 | |
|---|
| 100 | # top-level version of do-run which causes target to be built by |
|---|
| 101 | # default |
|---|
| 102 | rule run ( target : commands + ) |
|---|
| 103 | { |
|---|
| 104 | DEPENDS all : $(target) ; |
|---|
| 105 | do-run $(target) : $(commands) ; |
|---|
| 106 | } |
|---|
| 107 | |
|---|
| 108 | # experimental expected-failure version of run. This doesn't have |
|---|
| 109 | # quite the right semantics w.r.t. output dumping (it is still only |
|---|
| 110 | # dumped if the run fails), but we don't need run-fail anyway so it |
|---|
| 111 | # doesn't matter too much. |
|---|
| 112 | rule run-fail ( target : commands + ) |
|---|
| 113 | { |
|---|
| 114 | make-fail $(target) : $(commands) : do-run ; |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | # A command which will always fail to run. There is no file called |
|---|
| 118 | # nonexistent, so executing $(error) always causes an error. We can't |
|---|
| 119 | # just use `exit 1' below because that will cause all command |
|---|
| 120 | # processing to stop, and we want the rest of the do-run action |
|---|
| 121 | # command-line to execute. |
|---|
| 122 | error = $(CATENATE)" nonexistent" ; |
|---|
| 123 | |
|---|
| 124 | make-fail t1.txt : : create ; |
|---|
| 125 | make-fail t2.txt : : fail-to-create ; |
|---|
| 126 | make t3.txt : : create ; |
|---|
| 127 | make t4.txt : : fail-to-create ; |
|---|
| 128 | |
|---|
| 129 | run t5.txt : "( echo failing t5 && $(error) )" ; |
|---|
| 130 | run t6.txt : echo hi ; |
|---|
| 131 | |
|---|
| 132 | run-fail t7.txt : "( echo failing t7 && $(error) )" ; |
|---|
| 133 | run-fail t8.txt : echo hi ; |
|---|