|
| 1 | +-include ../tools.mk |
| 2 | + |
| 3 | +# Here's the basic overview: the crates all form a chain of dependencies, |
| 4 | +# |
| 5 | +# m6 -> m5 -> m4 -> m3 -> m2 -> m1 |
| 6 | +# |
| 7 | +# but: some crates have both rlibs and dylibs available, and others have only |
| 8 | +# rlib, or only dylib. |
| 9 | +# |
| 10 | +# m6 (app) -> m5 (rlib) -> m4 (dylib) -> m3 (rlib,dylib) -> m2 (lib) -> m1 (dylib,rlib) |
| 11 | +# |
| 12 | +# So the question we explore in this test is: What is the effect of `-C |
| 13 | +# prefer-dynamic` at different points in the chain. |
| 14 | +# |
| 15 | +# For example, if you try to build the above without *any* use of `-C |
| 16 | +# prefer-dynamic`, build of `m6` fails, because the compilation of dylib for |
| 17 | +# `m4` prefers the rlib for `m3` (which itself statically links the rlib for |
| 18 | +# `m1`). This is illustrated in v1 below. |
| 19 | + |
| 20 | +RLIB_TYPE=--crate-type rlib --cfg rlib_type |
| 21 | +DYLIB_TYPE=--crate-type dylib --cfg dylib_type |
| 22 | +LIB_TYPE=--crate-type lib --cfg lib_type |
| 23 | +BIN_TYPE=--crate-type bin --cfg bin_type |
| 24 | +PREFER_DYNAMIC_INPUT=-Zprefer-dynamic-subset -Cprefer-dynamic=std,m2,m3,$(1) |
| 25 | + |
| 26 | +# How to read this command sequence, for people unversed in shell scripting: |
| 27 | +# |
| 28 | +# I have tried to write useful comments as `echo` statements. Their text is usually |
| 29 | +# delimited by single quotes ('') rathern than double quotes ("") so that I can use |
| 30 | +# backticks (``) in the notes without it being interpreted as a shell invocation. |
| 31 | +# |
| 32 | +# `COMMAND && exit 1 && exit 0` is how we run a command and say that we're |
| 33 | +# expecting it to fail. |
| 34 | +# |
| 35 | +# `>&2 echo "stuff"` emits "stuff" to stderr; that's useful for humans reviewing |
| 36 | +# the error output on expected errors. |
| 37 | +# |
| 38 | +# (I'm not going so far as to programmatically verify the error output actually |
| 39 | +# matches our expectations here; that is a bridge too far. Instead, I'm just |
| 40 | +# trusting that if an error arises, its for the reason stated in the comment |
| 41 | +# emitted to stderr.) |
| 42 | +# |
| 43 | +# Note: you can add a `false` to the end of the recipe if you want to forcibly |
| 44 | +# see the stderr and stdout output captured in `compiletest`. |
| 45 | + |
| 46 | +all: |
| 47 | + echo 'v1: no extra flags, just see what default behavior is for this strange chain of crates.' |
| 48 | + >&2 echo '`m1` build as dylib and rlib, v1' |
| 49 | + $(RUSTC) m1.rs $(DYLIB_TYPE) |
| 50 | + $(RUSTC) m1.rs $(RLIB_TYPE) |
| 51 | + >&2 echo '`m2` build as lib, v1' |
| 52 | + $(RUSTC) m2.rs $(LIB_TYPE) |
| 53 | + >&2 echo '`m3` build as dylib, v1; no prefer-dynamic: expected to select rlib for `m1`' |
| 54 | + $(RUSTC) m3.rs $(DYLIB_TYPE) |
| 55 | + >&2 echo '`m3` build as rlib, v1' |
| 56 | + $(RUSTC) m3.rs $(RLIB_TYPE) |
| 57 | + >&2 echo '`m4` build as dylib, v1; no prefer-dynamic: expected to select rlib for `m3`' |
| 58 | + $(RUSTC) m4.rs $(DYLIB_TYPE) |
| 59 | + >&2 echo '`m5` build as rlib, v1' |
| 60 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 61 | + >&2 echo '`m6` build binary, v1: selects dylib for `m4`, because no rlib available' |
| 62 | + $(RUSTC) m6.rs $(BIN_TYPE) && exit 1 || exit 0 |
| 63 | + >&2 echo 'above expected to fail: `m1`, `m3` and `std` linked dynamically via `m6` and statically via `m4`.' |
| 64 | + |
| 65 | + echo 'v2: most immediate fix for problem from previous version: prefer-dynamic on `m4`.' |
| 66 | + >&2 echo '`m4` build as dylib v2: prefer-dynamic (selects dylibs for `std` and `m3`)' |
| 67 | + $(RUSTC) m4.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 68 | + >&2 echo '`m5` build as rlib v2' |
| 69 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 70 | + >&2 echo '`m6` build binary, v2: selects dylib for `m4`, because no rlib available' |
| 71 | + $(RUSTC) m6.rs $(BIN_TYPE) |
| 72 | + echo 'run `m6` v2' |
| 73 | + $(call RUN,m6) > $(TMPDIR)/v2.output |
| 74 | + echo 'expectation: prefer-dynamic on `m4` selected dylib for `m3`, while latter linked rlib for `m1`.' |
| 75 | + echo 'linkage: m6:bin m5:rlib m4:dylib m3:dylib m2:lib m1:rlib' > $(TMPDIR)/v2.expect |
| 76 | + diff -u $(TMPDIR)/v2.output $(TMPDIR)/v2.expect |
| 77 | + echo 'expectation: removing m4 dylib will cause run attempt to fail.' |
| 78 | + >&2 echo 'remove m4 dylib' |
| 79 | + $(call REMOVE_DYLIBS,m4) |
| 80 | + $(call FAIL,m6) |
| 81 | + >&2 echo 'rebuild m4 and check that recovered state.' |
| 82 | + $(RUSTC) m4.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 83 | + $(call RUN,m6) |
| 84 | + echo 'expectation: removing m3 dylib alone will cause run attempt to fail.' |
| 85 | + >&2 echo 'remove m3 dylib' |
| 86 | + $(call REMOVE_DYLIBS,m3) |
| 87 | + $(call FAIL,m6) |
| 88 | + >&2 echo 'rebuild m3 and check that recovered state.' |
| 89 | + $(RUSTC) m3.rs $(DYLIB_TYPE) |
| 90 | + $(call RUN,m6) |
| 91 | + echo 'expectation: removing m1 dylib and rlib will not perturb run v2 attempt.' |
| 92 | + >&2 echo 'remove `m1` rlib and dylib' |
| 93 | + $(call REMOVE_DYLIBS,m1) |
| 94 | + $(call REMOVE_RLIBS,m1) |
| 95 | + $(call RUN,m6) |
| 96 | + >&2 echo 'rebuild `m1` rlib and dylib' |
| 97 | + $(RUSTC) m1.rs $(RLIB_TYPE) |
| 98 | + $(RUSTC) m1.rs $(DYLIB_TYPE) |
| 99 | + |
| 100 | + echo 'v3: try `-C prefer-dynamic` when compiling `m2` now.' |
| 101 | + >&2 echo 'rebuild m1 dylib' |
| 102 | + $(RUSTC) m1.rs $(RLIB_TYPE) |
| 103 | + $(RUSTC) m1.rs $(DYLIB_TYPE) |
| 104 | + >&2 echo '`m2` build as lib, v3: prefer-dynamic (overall, still selects m1.rlib)' |
| 105 | + $(RUSTC) m2.rs $(LIB_TYPE) -C prefer-dynamic |
| 106 | + >&2 echo '`m3` build as dylib, v3' |
| 107 | + $(RUSTC) m3.rs $(DYLIB_TYPE) |
| 108 | + >&2 echo '`m3` build as rlib, v3' |
| 109 | + $(RUSTC) m3.rs $(RLIB_TYPE) |
| 110 | + >&2 echo '`m4` build as dylib v3: prefer-dynamic (to avoid duplicate static linkage)' |
| 111 | + $(RUSTC) m4.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 112 | + >&2 echo '`m5` build as rlib v3' |
| 113 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 114 | + >&2 echo '`m6` build bin v3' |
| 115 | + $(RUSTC) m6.rs $(BIN_TYPE) |
| 116 | + $(call RUN,m6) > $(TMPDIR)/v3.output |
| 117 | + echo 'expectation: prefer-dynamic on `m2` had no effect on which m1 got linked compared to previous.' |
| 118 | + echo 'linkage: m6:bin m5:rlib m4:dylib m3:dylib m2:lib m1:rlib' > $(TMPDIR)/v3.expect |
| 119 | + diff -u $(TMPDIR)/v3.output $(TMPDIR)/v3.expect |
| 120 | + |
| 121 | + echo 'v4: try `-C prefer-dynamic` when compiling `m3` now.' |
| 122 | + >&2 echo 'rebuild m1 dylib' |
| 123 | + $(RUSTC) m1.rs $(RLIB_TYPE) |
| 124 | + $(RUSTC) m1.rs $(DYLIB_TYPE) |
| 125 | + >&2 echo '`m2` build as lib, v4' |
| 126 | + $(RUSTC) m2.rs $(LIB_TYPE) |
| 127 | + >&2 echo '`m3` build as dylib, v4; prefer-dynamic, and now selects m1.dylib' |
| 128 | + $(RUSTC) m3.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 129 | + >&2 echo '`m3` build as rlib, v4: prefer-dynamic' |
| 130 | + $(RUSTC) m3.rs $(RLIB_TYPE) -C prefer-dynamic |
| 131 | + >&2 echo '`m4` build as dylib v4' |
| 132 | + $(RUSTC) m4.rs $(DYLIB_TYPE) |
| 133 | + >&2 echo '`m5` build as rlib v4' |
| 134 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 135 | + >&2 echo '`m6` build bin v4: selects dylib for `m4`, because no rlib available' |
| 136 | + $(RUSTC) m6.rs $(BIN_TYPE) && exit 1 || exit 0 |
| 137 | + >&2 echo 'above expected to fail: `std` linked dynamically via `m6` and statically via `m4`.' |
| 138 | + |
| 139 | + echo 'v5: try `-C prefer-dynamic` when compiling `m3` now.' |
| 140 | + >&2 echo 'rebuild m1 dylib' |
| 141 | + $(RUSTC) m1.rs $(RLIB_TYPE) |
| 142 | + $(RUSTC) m1.rs $(DYLIB_TYPE) |
| 143 | + >&2 echo '`m2` build as lib, v5' |
| 144 | + $(RUSTC) m2.rs $(LIB_TYPE) |
| 145 | + >&2 echo '`m3` build as dylib, v5; prefer-dynamic, and now selects dylib for `m1`.' |
| 146 | + $(RUSTC) m3.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 147 | + >&2 echo '`m3` build as rlib, v5: prefer-dynamic; it nonetheless resolves to rlib for `m1`' |
| 148 | + $(RUSTC) m3.rs $(RLIB_TYPE) -C prefer-dynamic |
| 149 | + >&2 echo '`m4` build as dylib v5; prefer-dynamic just for std, not m3' |
| 150 | + $(RUSTC) m4.rs $(DYLIB_TYPE) -C prefer-dynamic=std -Z prefer-dynamic-std |
| 151 | + >&2 echo '`m5` build as rlib v5' |
| 152 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 153 | + >&2 echo '`m6` build bin v5; prefer-dynamic just for `m4` and `std`, not `m3`' |
| 154 | + $(RUSTC) m6.rs $(BIN_TYPE) -C prefer-dynamic=std,m4 -Z prefer-dynamic-subset |
| 155 | + $(call RUN,m6) > $(TMPDIR)/v5.output |
| 156 | + echo 'expectation: prefer-dynamic=std,m4 on `m4`/`m6` meant m3 rlib gets linked, and m3 rlib links m1 rlib.' |
| 157 | + echo 'linkage: m6:bin m5:rlib m4:dylib m3:rlib m2:lib m1:rlib' > $(TMPDIR)/v5.expect |
| 158 | + diff -u $(TMPDIR)/v5.output $(TMPDIR)/v5.expect |
| 159 | + |
| 160 | + echo 'v6: try `-C prefer-dynamic` when `m3` and `m4` now.' |
| 161 | + >&2 echo '`m4` build as dylib v6; prefer-dynamic for everything; selects dylib for `m3`.' |
| 162 | + $(RUSTC) m4.rs $(DYLIB_TYPE) -C prefer-dynamic |
| 163 | + >&2 echo '`m5` build as rlib v6' |
| 164 | + $(RUSTC) m5.rs $(RLIB_TYPE) |
| 165 | + >&2 echo '`m6` build bin v6: selects dylib for `m4` and thus for `m3` and `m1`.' |
| 166 | + $(RUSTC) m6.rs $(BIN_TYPE) |
| 167 | + $(call RUN,m6) > $(TMPDIR)/v6.output |
| 168 | + echo 'expectation: prefer-dynamic on `m3`/`m4` meant m3 dylib gets linked, and m3 dylib links m1 dylib.' |
| 169 | + echo 'linkage: m6:bin m5:rlib m4:dylib m3:dylib m2:lib m1:dylib' > $(TMPDIR)/v6.expect |
| 170 | + diff -u $(TMPDIR)/v6.output $(TMPDIR)/v6.expect |
| 171 | + |
| 172 | +# >&2 echo 'reached final false' |
| 173 | +# false |
| 174 | + |
| 175 | +# Note: you can add a `false` to the end of the recipe if you want to forcibly |
| 176 | +# see the stderr and stdout output captured in `compiletest`. |
0 commit comments