Skip to content

Commit 21778cb

Browse files
committed
run-make test exploring behavior of -C prefer-dynamic.
1 parent 5509ab2 commit 21778cb

File tree

8 files changed

+240
-0
lines changed

8 files changed

+240
-0
lines changed

Diff for: src/test/run-make-fulldeps/dylib-subset/Makefile

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
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`.
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#[cfg(bin_type)]
2+
pub fn crate_type() -> &'static str { "bin" }
3+
4+
#[cfg(lib_type)]
5+
pub fn crate_type() -> &'static str { "lib" }
6+
7+
#[cfg(dylib_type)]
8+
pub fn crate_type() -> &'static str { "dylib" }
9+
10+
#[cfg(rlib_type)]
11+
pub fn crate_type() -> &'static str { "rlib" }
12+
13+
// (The cases below are not used in any of these tests yet. But it might be good
14+
// to think about adding them.)
15+
16+
#[cfg(staticlib_type)]
17+
pub extern "C" fn crate_type() -> *const u8 { "staticlib\0".as_ptr() }
18+
19+
#[cfg(cdylib_type)]
20+
pub extern "C" fn crate_type() -> *const u8 { "cdylib\0".as_ptr() }

Diff for: src/test/run-make-fulldeps/dylib-subset/m1.rs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod common_body;
2+
3+
pub fn linkage_chain() -> String {
4+
format!("m1:{}", ::common_body::crate_type())
5+
}

Diff for: src/test/run-make-fulldeps/dylib-subset/m2.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern crate m1 as next;
2+
3+
mod common_body;
4+
5+
pub fn linkage_chain() -> String {
6+
format!("m2:{} {}", crate::common_body::crate_type(), next::linkage_chain())
7+
}

Diff for: src/test/run-make-fulldeps/dylib-subset/m3.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern crate m2 as next;
2+
3+
mod common_body;
4+
5+
pub fn linkage_chain() -> String {
6+
format!("m3:{} {}", crate::common_body::crate_type(), next::linkage_chain())
7+
}

Diff for: src/test/run-make-fulldeps/dylib-subset/m4.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern crate m3 as next;
2+
3+
mod common_body;
4+
5+
pub fn linkage_chain() -> String {
6+
format!("m4:{} {}", ::common_body::crate_type(), next::linkage_chain())
7+
}

Diff for: src/test/run-make-fulldeps/dylib-subset/m5.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
extern crate m4 as next;
2+
3+
mod common_body;
4+
5+
pub fn linkage_chain() -> String {
6+
format!("m5:{} {}", crate::common_body::crate_type(), next::linkage_chain())
7+
}

Diff for: src/test/run-make-fulldeps/dylib-subset/m6.rs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
extern crate m5 as next;
2+
3+
mod common_body;
4+
5+
pub fn linkage_chain() -> String {
6+
format!("m6:{} {}", ::common_body::crate_type(), next::linkage_chain())
7+
}
8+
9+
fn main() {
10+
println!("linkage: {}", linkage_chain());
11+
}

0 commit comments

Comments
 (0)