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

Implement RFC 1717 #37973

Merged
merged 9 commits into from
Dec 6, 2016
Merged

Implement RFC 1717 #37973

merged 9 commits into from
Dec 6, 2016

Conversation

vadimcn
Copy link
Contributor

@vadimcn vadimcn commented Nov 24, 2016

Implement the first two points from #37403.

r? @alexcrichton

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 24, 2016

cc @retep998

Copy link
Member

@alexcrichton alexcrichton left a comment

Choose a reason for hiding this comment

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

Looks good! Some further thoughts:

  • At the same time, this should supplant #[linked_from], can all usages of that be replaced with this?
  • Shouldn't dllexport get hooked up into this infrastructure as well?

if item.name == name {
item.kind = new_kind;
if let Some(new_name) = new_name {
item.name = Symbol::intern(new_name);
Copy link
Member

Choose a reason for hiding this comment

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

Could we take an extra conservative route here and avoid multiple indirections of libraries? Ideally each library would be renamed at most once and wouldn't have to worry about what order we process options in.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure what you mean by "multiple indirections"... Is this about the fact that there may be several NativeLibrary entries for the same library? I don't think we can just merge them,- because library ordering on linker's command line is important.

Copy link
Member

Choose a reason for hiding this comment

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

Oh I mean something like:

rustc -l foo:bar -l bar:baz -l baz:real-name

We shouldn't allow something like that and a lib should be "renamed" at most once.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok. Just want to note that this behavior is occasionally useful when you want to override something by appending to a pre-composed command line (usually comes up in makefiles and such).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@alexcrichton: How far did you want to take this checking?

Currently the following are allowed:
-l foo -l foo
-l static=foo -l dylib=foo
which would result in adding foo to the linker command line twice.

Under the new rules, this will merely change the kind of foo two times (assuming it's been defined in crate source, and if not... I am not sure).

It feels a bit weird to allow chaining for kind alterations, but not for names.

Perhaps this part of the RFC merits additional discussion.

Copy link
Member

Choose a reason for hiding this comment

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

Hm that does sound like an unfortunate "regression", but I'd imagine that in practice that was doomed to never link correctly anyway?

It does seem like we can't strictly require that -lfoo isn't specified more than once, but perhaps we can still be strict about renamings where a lib is only renamed once?

cfg: None,
foreign_items: Vec::new(),
};
register_native_lib(self.sess, self.cstore, None, lib);
Copy link
Member

Choose a reason for hiding this comment

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

In this case the new_name is thrown away, but isn't that the name the library should be linked under?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. Yes, I should use new_name here, if available.
Probably also emit a warning?

Copy link
Member

Choose a reason for hiding this comment

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

Hm actually given the option to do so let's make this a hard error to be conservative.

@@ -98,7 +98,7 @@ mod tests {
#[derive(Copy, Clone)]
pub struct Floats { a: f64, b: u8, c: f64 }

#[link(name = "rust_test_helpers")]
#[link(name = "rust_test_helpers", kind = "static")]
Copy link
Member

Choose a reason for hiding this comment

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

Were these changes (and those below) required? If so that may be quite worrisome as this is a breaking change...

Copy link
Contributor Author

@vadimcn vadimcn Nov 28, 2016

Choose a reason for hiding this comment

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

rust_test_helpers is a static lib, so it started failing on Windows after this change. Granted it was only a couple of tests that used the rust_dbg_static_mut export, but I did a bulk change for consistency sake.

So yeah, there is some potential for breakage, but importing data from a library is a relatively rare thing, and it was already broken on Windows half the time. Not sure how to assess the extent of this breakage though. There is no such thing as Windows crater, right?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah unfortunately no crater coverage just yet, but to be clear the failure mode here was:

  • The linkage was incorrectly tagged
  • The library only pulled in statics
  • We then spit out a linker error

If that's the case then yeah seems like ok breakage. There's a way to fix it to work on all rustc versions, and otherwise we're just fixing a bug.

@retep998
Copy link
Member

Shouldn't dllexport get hooked up into this infrastructure as well?

Specifically, if an extern symbol is known to come from a static library, and that extern symbol is reachable in a dylib (including indirectly via inlining and monomorphization) or publicly re-exported in a cdylib, then it should go in the list of symbols to be exported in the .def file that rustc passes to the linker.

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 28, 2016

Shouldn't dllexport get hooked up into this infrastructure as well?

I thought we already did this (export all reachable public symbols via a .def file)?
@retep998, which cases aren't working right now?

@retep998
Copy link
Member

@vadimcn We do export all reachable stuff right now, except for extern symbols pulled in from static libraries. If libfoo.dll (crate type of dylib) links to the static library bar.lib (kind of static or static-nobundle), and some symbols from bar.lib are reachable externally from the dylib, then they will need to be exported. This edge case is what #[linked_from] was specifically designed to fix, and because this PR will replace #[linked_from], it will need to be able to handle that edge case.

@alexcrichton
Copy link
Member

@vadimcn I suppose both of my points should get lumped into one. The #[linked_from] is that infrastructure, but the purpose of the RFC was to delete #[linked_from]

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 28, 2016

As-implemented, #[link] does the same thing as #[linked_from]. So I'll remove #[linked_from] then...

I've noticed, though, that upstream publics are exported only for dylibs. Cdylibs export just their own public symbols. @alexcrichton: is it supposed to be this way, or was this case overlooked when cdylibs were added?

@alexcrichton
Copy link
Member

@vadimcn hm I believe that's overlooked, cdylibs shouldn't be exporting statically linked libraries.

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 29, 2016

I believe that's overlooked, cdylibs shouldn't be exporting statically linked libraries.

Shouldn't or should? Right now they don't, so this sentence seems self-contradictory :-/

@retep998
Copy link
Member

retep998 commented Nov 29, 2016

If I have an extern "C" { fn foo(...); } somewhere and then in the root of a cdylib I do pub use whatever::foo;, and foo comes from a static library, then I'd very much expect foo to be exported from the cdylib. If I don't do pub use whatever::foo; however, then it should not be exported.

@alexcrichton
Copy link
Member

Oh sorry, I misinterpreted. If we have a "bug" where we export fewer symbols let's keep it that way. Easier to later export symbols than to hide them.

@retep998
Copy link
Member

We do currently incorrectly export some functions from cdylibs which shouldn't be exported, so fixing that would be really nice. #34493

@vadimcn
Copy link
Contributor Author

vadimcn commented Nov 29, 2016

I'm talking about this case:

#![crate_type = "cdylib"]

#[link(name = "native", kind="static")]
extern "C" {
    pub fn static_func2(x: i32) -> i32;
    pub static static_global2: i32;
}

#[no_mangle]
pub extern "C" fn local() {}

Right now only the local gets exported.

@retep998
Copy link
Member

@vadimcn Because static_func2 and static_global2 are both pub, have unmangled names, and are in the root of a cdylib, I'd definitely prefer that they be exported as well.

@alexcrichton
Copy link
Member

@vadimcn I'm fine classifying that as a bug, but I'm also fine not explicitly fixing that here unless it just happens to fall out naturally.

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 2, 2016

Removed "linked_from" and added more error checking.
r?

@alexcrichton
Copy link
Member

@bors: r+

Looks great to me, thanks @vadimcn!

@bors
Copy link
Contributor

bors commented Dec 2, 2016

📌 Commit a23c470 has been approved by alexcrichton

@alexcrichton alexcrichton added the relnotes Marks issues that should be documented in the release notes of the next release. label Dec 2, 2016
lib.name = Symbol::intern(new_name);
}
found = true;
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

How does this break live along with the (there may be more than one) comment?

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 2, 2016

How does this break live along with the (there may be more than one) comment?

You are right, it doesn't :(

@bors: r-

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 3, 2016

@bors: r=alexcrichton

@bors
Copy link
Contributor

bors commented Dec 3, 2016

📌 Commit 923034f has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Dec 3, 2016

⌛ Testing commit 923034f with merge 32e99bd...

@bors
Copy link
Contributor

bors commented Dec 3, 2016

💔 Test failed - auto-win-gnu-32-opt-rustbuild

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 3, 2016

Hrm, is there a way to restrict a test to -windows-msvc only?

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 3, 2016

@bors: r=alexcrichton

@bors
Copy link
Contributor

bors commented Dec 3, 2016

📌 Commit 2e03549 has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Dec 4, 2016

⌛ Testing commit 2e03549 with merge 925bc9b...

@bors
Copy link
Contributor

bors commented Dec 4, 2016

💔 Test failed - auto-win-msvc-64-opt-rustbuild

@vadimcn
Copy link
Contributor Author

vadimcn commented Dec 6, 2016

Turns out I never ran the full test suite on a Windows host. :-/
Added code to handle #[link(cfg=...)].
r?

@alexcrichton
Copy link
Member

@bors: r+

@bors
Copy link
Contributor

bors commented Dec 6, 2016

📌 Commit 7d05d1e has been approved by alexcrichton

@bors
Copy link
Contributor

bors commented Dec 6, 2016

⌛ Testing commit 7d05d1e with merge 1692c0b...

bors added a commit that referenced this pull request Dec 6, 2016
Implement RFC 1717

Implement the first two points from #37403.

r? @alexcrichton
let mut found = false;
for lib in self.cstore.get_used_libraries().borrow_mut().iter_mut() {
if lib.name == name as &str {
lib.kind = kind;
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this mean the a kind specified in the source will be silently overwritten?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants