Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] parameterize -C prefer-dynamic #88101

Conversation

pnkfelix
Copy link
Member

@pnkfelix pnkfelix commented Aug 17, 2021

see also MCP rust-lang/compiler-team#455

This PR generalizes -C prefer-dynamic so that one can specify a specific subset of the crates that should have the preferred-dynamic linkage.

Without this PR, one generally has to decide globally whether dynamic linkage will be preferred (via -C prefer-dynamic=on, or just -C prefer-dynamic) or if static linkage will be preferred (via -C prefer-dynamic=off, or just omitting the option entirely). The fact that this is a global choice means that one can get into tricky scenarios where, because of choices made by your crate dependencies for what output types they generate, your crate hits strange linkage errors. (For one example of this, see #82151.)

There are multiple ways to address the above problem, such as changing the crate dependencies to reduce the kinds of output crate types they generate (see e.g. alexkornitzer/hyper@1199048), or choosing -C prefer-dynamic=no to stop rustc from injecting linkage directives, and then adding on additional RUSTFLAGS=-l<crate_name> flags to explicitly link to the dynamic libraries you want.

This PR suggests a different way to address it: By allowing the user to specify a list of crates, -C prefer-dynamic=crate1,crate2,... they believe should be given preferred dynamic linkage.

Since std comes up as a common example here, -C prefer-dynamic=std is given special treatment. You can opt into arbitrary lists of crates via -Z prefer-dynamic-subset. Or you can enable the use of the singleton command line option -C prefer-dynamic=std via -Z prefer-dynamic-std.

  • My intent, in making separate -Z flags for these cases, is to fast track the stabilization of -C prefer-dynamic=std, because I think that will provide the biggest impact, and has relatively low risk (in terms of it not having potential for exposing sharp corners of rustc's internal heuristics for determining dynamic linkage). We can let the more general -C prefer-dynamic=crate1,crate2,... simmer; for example, we may want to make more changes to how chains of rlibs and dylibs are handled, and that may interact with the prefer-dynamic-subset feature.

@rust-highfive
Copy link
Collaborator

r? @jackh726

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 17, 2021
@rust-log-analyzer

This comment has been minimized.

@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from 83f3499 to dff2577 Compare August 17, 2021 02:35
@pnkfelix
Copy link
Member Author

The job mingw-check failed! Check out the build log: (web) (plain)
Click to see the possible cause of the failure (guessed by this bot)

No rest for the wicked.

(I got punished for adding type annotations of the form Rc<CrateSource> when the actual type was of Lrc, not Rc, which are sometimes, but not always, type aliases.)

@rust-log-analyzer

This comment has been minimized.

@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from dff2577 to 0093bb6 Compare August 17, 2021 03:04
@rust-log-analyzer

This comment has been minimized.

@pnkfelix
Copy link
Member Author

Hmm, yeah I was worried about something like this:

1 error: linking with `cc` failed: exit status: 1
2    |
-    = note: "cc" "-m64" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn.issue_82151_serverctl_prefdyn.72d5a704-cgu.0.rcgu.o" "-Wl,--as-needed" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lshared" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lbar" "-Wl,--start-group" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-lstd-f2409c1bc0340a9e" "-Wl,--end-group" "-Wl,-Bstatic" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-bc417570076b2daa.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-Wl,-rpath,$ORIGIN/auxiliary" "-Wl,-rpath,$ORIGIN/../../../../stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--enable-new-dtags"
-    = note: /usr/bin/ld: $TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary/libshared.so: undefined reference to `bar::bar'
+    = note: "cc" "-m64" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn.issue_82151_serverctl_prefdyn.72d5a704-cgu.0.rcgu.o" "-Wl,--as-needed" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lshared" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lbar" "-Wl,--start-group" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-lstd-979615b1d869d792" "-Wl,--end-group" "-Wl,-Bstatic" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-52fe0581016e3544.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-Wl,-rpath,$ORIGIN/auxiliary" "-Wl,-rpath,$ORIGIN/../../../../stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--enable-new-dtags"
+    = note: $TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary/libshared.so: undefined reference to `bar::bar'
5            collect2: error: ld returned 1 exit status
Some tests failed in compiletest suite=ui mode=ui host=x86_64-unknown-linux-gnu target=x86_64-unknown-linux-gnu
6            
7    = help: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified

i.e. the error output is tightly coupled to the linker's error formatting.

I'll go see if I can use one of the old coarser grain error-pattern checking systems. Hopefully those haven't been retired yet. :)

@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from 0093bb6 to d483cd8 Compare August 17, 2021 03:55
@rust-log-analyzer

This comment has been minimized.

@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from d483cd8 to 411bdf5 Compare August 17, 2021 04:22
Added reverse map that tells us for a given dependency and its preferred format,
what were the parent crates that requested that dependency+format combination.
(type annotations are to help rust-analyzer as much as humans.)
…tes to prefer dynamic linkage on.

Note: carrying an empty set here is *not* the same as `-C prefer-dyanmic=no`
(and the latter is the default behavior for `rustc`). As discussed in detail in
the comments for `enum PreferDynamicSet` (and also in the comments of
`rustc_metadata::dependency_format`), `-C prefer-dynamic=no` asks the compiler
to guess what linkage to use, and it currently guesses all static first, and if
that fails, then it prefers dynamic linkage for all crates that provide both
dynamic and static libraries.

Using an empty set for `-C prefer-dynamic`, on the other hand, means the
compiler should never prefer dynamic linkage over static linkage, even if that
means it won't be able to successfully link the build product.
@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from 411bdf5 to d0089c8 Compare August 17, 2021 04:27
@rust-log-analyzer

This comment has been minimized.

@petrochenkov petrochenkov self-assigned this Aug 17, 2021
@jackh726 jackh726 removed their assignment Aug 17, 2021
@pnkfelix
Copy link
Member Author

One thing still missing from this PR is a run-make test illustrating that the dynamically linked libraries are the set that we expect. The usual pattern for testing that, which you can see in existing run-make tests, is to run the binary successfully, then delete the dylib and attempt to re-run the binary, now expecting a runtime failure. I do plan to add some run-make tests in that vein to this PR; I just wanted to get this up and get some review feedback on it before I invested time on that.

@pnkfelix
Copy link
Member Author

pnkfelix commented Aug 17, 2021

-    = note: "cc" "-m64" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn.issue_82151_serverctl_prefdyn.72d5a704-cgu.0.rcgu.o" "-Wl,--as-needed" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lshared" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lbar" "-Wl,--start-group" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-lstd-*" "-Wl,--end-group" "-Wl,-Bstatic" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-*.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-Wl,-rpath,$ORIGIN/auxiliary" "-Wl,-rpath,$ORIGIN/../../../../stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--enable-new-dtags"
+    = note: "cc" "-m64" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn.issue_82151_serverctl_prefdyn.72d5a704-cgu.0.rcgu.o" "-Wl,--as-needed" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lshared" "-L" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/auxiliary" "-lbar" "-Wl,--start-group" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-lstd-*" "-Wl,--end-group" "-Wl,-Bstatic" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcompiler_builtins-*.rlib" "-Wl,-Bdynamic" "-lgcc_s" "-lutil" "-lrt" "-lpthread" "-lm" "-ldl" "-lc" "-Wl,--eh-frame-hdr" "-Wl,-znoexecstack" "-L" "$BUILD_DIR/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-o" "$TEST_BUILD_DIR/dylibs/issue-82151-serverctl-prefdyn/issue-82151-serverctl-prefdyn" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-Wl,-rpath,$ORIGIN/auxiliary" "-Wl,-rpath,$ORIGIN/../../../../stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,--enable-new-dtags"

Okay I'll need to normalize the stage{1,2} in the stderr output too.

@pnkfelix pnkfelix force-pushed the issue-82151-parameterize-prefer-dynamic branch from d0089c8 to 3c0b75d Compare August 17, 2021 18:45
let link2_parent_names = parent_names(link2);

let details = match (link2, link) {
(RequireDynamic, RequireStatic) => format!(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💖

}
}

pub fn contains_crate(&self, crate_name: Symbol) -> bool {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think using just the crate name is not a good idea. It doesn't allow distinguishing between two different versions of the same library. Ideally it would accept the StableCrateId, but that is not accessible outside of rustc without depending on nightly (-Zls?) or implementation details. Maybe also allow accepting a dylib path or combination of crate name, if it has bin as crate type in addition to dylib and the list of -Cmetadata arguments. The StableCrateId is reproducible using just this information. I don't think we can't change what it depends on as that would change which crates can be linked into the same crate graph and which can't: https://github.com/rust-lang/rust/blob/master/compiler/rustc_span/src/def_id.rs#L148-L175

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would some encoding of crate name and an optionally-supplied version be sufficient to satisfy your criteria here? I'm thinking in the common cases, a single crate name is exactly what an end user will want to write down.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that would work I guess. Cargo could specify everything and a user just the crate name.

Some(s) => {
let v = s.split(',').map(|s| s.to_string()).collect();
PreferDynamicSet::Set(v)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be a different argument as the new option is not a preference, but mandatory?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. My intention was that it would still be a preference, in the sense that if you do -C prefer-dynamic=crate1, but only a static library for crate1 is available, then linkage will still proceed using the static library.

I probably should add a test illustrating that.

Copy link
Member Author

@pnkfelix pnkfelix Aug 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On reflection, I do think I must have messed up something in my logic that ends up making something a requirement rather than a preference. Specifically, I'm working on a run-make test analogous to https://github.com/rust-lang/rust/blob/master/src/test/run-make-fulldeps/dylib-chain/Makefile
but where I choose variations of whether dylibs on the chain have both rlib and dylib, or just rlib, or just dylib.

The problem I'm seeing is that in some scenarios using -C prefer-dynamic=crate,..., a crate that is solely provided as a dylib is not getting linked in unless I include it in the above list. That wasn't my intention here: My intention was that the preference is meant to give guidance when the compiler must make a choice, not act as an assertion about what it expects to be present.

Update: I forgot that of course the choice isn't necessarily about which file to link in; you can still statically link a .dylib file. So even if I generate just a .dylib for some crate in the chain, the crates linking to it still have a choice to make, and this flag is going to affect that choice.

(Or at least, that's my current interpretation of the behavior I'm observing. Still digging a bit deeper.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update 2: Hmm maybe I was wrong about the above: In general .so files don't have enough info to be statically linked. But then I'm really confused about some of the behavior I'm seeing. Still looking.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I have now made a run-make test that I think illustrates the current behavior of the system, including cases where rlib's end up depending on dylibs.

I don't think pre-existing behavior is necessarily intuitive, but my main goal right now is to address missing use cases, not to try to figure out what the ideal behavior is for all cases and potentially inject breaking changes to support that idealized behavior.


Note that the explicit list of crate names variant of this flag is gated behind
`-Zprefer-dynamic-subset`; as a special case, one can enable the handling of
the single crate `std` as shown in the example above via `-Zprefer-dynamic-std`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those options don't exist at least as of this commit.

Edit: these are introduced in the next commit.

// skip traversal if we know it cannot ever bear fruit.
false
} else {
tcx.crates(()).iter().any(|cnum| prefer_dynamic.contains_crate(tcx.crate_name(*cnum)))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should skip non-linkable crates like proc-macros and their dependencies I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I'll look into that.


pub fn check_linked_function_equivalence() {
// Check that the linked functions are the same code by comparing their
// underlying addresses.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't be surprised if the dynamic linker would resolve each symbol with the same name to the same address at runtime even if it is duplicated between dylibs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly... I have certainly been thinking that the testing methodology here might be flawed. I'm still musing about the best way to write these tests (i.e. to detect unwanted duplication of static libraries across dynamic libraries being loaded).

I'm still planning to invest some effort into a run-make test, to check the most basic scenario of deleting a dynamic library and observing that this injects a failure to run the binary. But that isn't quite the same check that I'm trying to put in here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could do an objdump of dylibs to check which symbols are defined and imported. Imported symbols use 0 as specified address.

Copy link
Member Author

@pnkfelix pnkfelix Aug 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay I added a run-make test; it does two things:

  1. it uses the pre-existing pattern of building, running to success, then deleting dylibs, and checking that a re-run attempt fails. (I think this testing methodology is fine, as far as it goes.)
  2. it introduces a new pattern of having methods in the compiled code that differ depending on whether one is linked to the rlib or to the dylib. This is controlled via cfg flags. This way, we can directly determine which object code has been linked and loaded when we finally run the program.

@rust-log-analyzer

This comment has been minimized.

@jackh726
Copy link
Member

r? @bjorn3

@pnkfelix
Copy link
Member Author

pnkfelix commented Aug 19, 2021

It is worth explicitly noting: The run-make test I added in 21778cb has six variant tests (v1 through v6), but only one of them, v5, actually exercises -Z prefer-dynamic-subset and -Z prefer-dynamic-std.

The other five tests, v1-4 and 6, all work without debugflags, and represent pre-existing behavior.

I have manually confirmed that those five tests all work as written on the compiler before the changes in this PR. In other words, the test is largely codifying the pre-existing behavior of -C prefer-dynamic (for better or for worse; I am still working out what the mental model of a user for the pre-existing behavior is meant to be here).

# delimited by single quotes ('') rathern than double quotes ("") so that I can use
# backticks (``) in the notes without it being interpreted as a shell invocation.
#
# `COMMAND && exit 1 && exit 0` is how we run a command and say that we're
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# `COMMAND && exit 1 && exit 0` is how we run a command and say that we're
# `COMMAND && exit 1 || exit 0` is how we run a command and say that we're

@inquisitivecrystal inquisitivecrystal added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Aug 24, 2021
@petrochenkov
Copy link
Contributor

petrochenkov commented Sep 2, 2021

I left some comments on the Zulip MCP thread https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/prefer-dynamic.3Dsubset.20compiler-team.23455

The whole idea is a pretty big hack, that is not much better than the workarounds that exist currently.
It breaks through all the careful versioning and hashes used by cargo and rustc to uniquely identify crates.
I guess it's suitable if your build is on fire and you need to extinguish it right now, but it's not something I'd personally want to stabilize.

The main problem is that there's no clean way to refer to indirect dependencies of a crate, because they are identified by hash (the crate name is used to prune the file search space, but it's not an identifier).
The hash is internal and is not visible even to build system.

For crates controlled by cargo (or other build system) the build system can identify the crate by (one of) its file path(s), and pass that path to rustc which would retrieve the hash from it.
However that wouldn't work for crates not controlled by cargo and found purely by name (with std being the main example), unless we add, for example, a new rustc --print option for retrieving a crate file path by name.

(I also have comments about the specific implementation in this PR, but I'll leave them for the later time when the general direction is settled.)

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Sep 2, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Sep 20, 2021
@petrochenkov
Copy link
Contributor

petrochenkov commented Sep 24, 2021

Another idea is to use the fact that rustc "unifies" crates pointing to the same file and assigns a single CrateNum to them, regardless of whether they are linked directly or indirectly.
(That's why std::vec::Vec used directly from std and reexported through some other crate refer to the same type and DefId.)

So to refer to an indirect dependency we can add a new direct dependency referring to our crate of interest (by path --extern name=PATH, or by name --extern name), and then use an --extern modifier --extern prefer-dynamic:name=PATH (similar to existing --extern priv:name=PATH and --extern noprelude:name=PATH) to attach the "prefer-dynamic" property to the corresponding CrateNum.

@pnkfelix
Copy link
Member Author

pnkfelix commented Sep 30, 2021

Another idea is to use the fact that rustc "unifies" crates pointing to the same file and assigns a single CrateNum to them, regardless of whether they are linked directly or indirectly. (That's why std::vec::Vec used directly from std and reexported through some other crate refer to the same type and DefId.)

So to refer to an indirect dependency we can add a new direct dependency referring to our crate of interested (by path --extern name=PATH, or by name --extern name), and then use an --extern modifier --extern prefer-dynamic:name=PATH (similar to existing --extern priv:name=PATH and --extern noprelude:name=PATH) to attach the "prefer-dynamic" property to the corresponding CrateNum.

Sorry, @petrochenkov , I am not fully understanding this.

When you say "to refer to an indirect dependency we can add a new direct dependency referring to our crate of interested", do you mean "refer" as in what internal data structures that rustc uses to denote an indirect dependency?

Or are you somehow suggesting a different way of invoking the existing rustc compiler to work around this problem? (An interpretation that doesn't seem plausible...)

@petrochenkov
Copy link
Contributor

@pnkfelix

When you say "to refer to an indirect dependency we can add a new direct dependency referring to our crate of interested", do you mean "refer" as in what internal data structures that rustc uses to denote an indirect dependency?

Maybe, but I don't understand what you mean here.

Or are you somehow suggesting a different way of invoking the existing rustc compiler to work around this problem? (An interpretation that doesn't seem plausible...)

Certainly not this.

By "refer to a crate X" I mean "somehow name that crate from command line".
Once we can name it we can attach various properties like prefer-dynamic to it.

@bors
Copy link
Contributor

bors commented Oct 5, 2021

☔ The latest upstream changes (presumably #89266) made this pull request unmergeable. Please resolve the merge conflicts.

@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 24, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Nov 8, 2021
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 5, 2021
@joelpalmer joelpalmer added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 1, 2022
@JohnCSimon JohnCSimon added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 27, 2022
@pnkfelix pnkfelix changed the title parameterize -C prefer-dynamic [WIP] parameterize -C prefer-dynamic Mar 4, 2022
@pnkfelix
Copy link
Member Author

pnkfelix commented Mar 4, 2022

I'm going to revisit my approach here, maybe try to work out something that better leverages things like PR #93901, (assuming that lands).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants