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

Support dylib with prefer-dynamic properly #3406

Open
ishitatsuyuki opened this issue Dec 15, 2016 · 4 comments
Open

Support dylib with prefer-dynamic properly #3406

ishitatsuyuki opened this issue Dec 15, 2016 · 4 comments
Labels
A-configuration Area: cargo config files and env vars A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.

Comments

@ishitatsuyuki
Copy link
Contributor

The behavior that doesn't apply prefer-dynamic for anything linked to dylib or the dylib itself seems a flaw. This triggers errors like rust-lang/rust#19680.

Configuration: (project metadata omitted)

[lib]
crate-type = ["dylib"]

([bin] is implicitly created)

#1496 is also a result of this flaw. There's no reason to disable it intendedly.

@carols10cents carols10cents added A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` A-configuration Area: cargo config files and env vars labels Sep 29, 2017
@ehuss ehuss added the S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request. label May 23, 2023
@lvella
Copy link

lvella commented Jun 27, 2023

I disagree this is a feature request. This is bug.

If you need more info, this is how I triggered it.

I am trying to wrap rug in a "dylib" so I can link it with non-LGPL code, but it fails catastrophically. Source contains a single line:

pub use rug::*;

The test sums 2 numbers:

#[test]
fn sum() {
    let a = rug_dynamic::Integer::from_str_radix("1000000000000000000000000000000000", 10).unwrap();
    let b = rug_dynamic::Integer::from(42);

    assert_eq!(
        a + b,
        rug_dynamic::Integer::from_str_radix("1000000000000000000000000000000042", 10).unwrap()
    );
}

Repo is here: https://github.com/lvella/rug-dynamic

Simply run cargo test and you will see:

error: cannot satisfy dependencies so `std` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `core` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `compiler_builtins` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `rustc_std_workspace_core` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `alloc` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `libc` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `unwind` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `cfg_if` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `miniz_oxide` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `rustc_std_workspace_alloc` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `adler` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `hashbrown` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `std_detect` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `rustc_demangle` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `addr2line` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `gimli` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `object` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `memchr` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: cannot satisfy dependencies so `panic_unwind` only shows up once
  |
  = help: having upstream crates all available in one format will likely make this go away

error: could not compile `rug-dynamic` due to 19 previous errors

@bjorn3
Copy link
Member

bjorn3 commented Jun 27, 2023

Disclaimer: IANAL

I am trying to wrap rug in a "dylib" so I can link it with non-LGPL code

According to section 4 Combined Works:

You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following:

[...]

  • d) Do one of the following:
      1. Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.
      1. Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version.

Option 1 doesn't work with the rust dylib crate type as when you change the dynamic library it will almost certainly be ABI incompatible even when it is still interface-compatible. (It is guaranteed to be ABI incompatible when a different -Cmetadata argument is passed from what was used when previously compiling it and when #[inline] or generic functions are changed) As such you either have to create a stable C abi with the cdylib crate type or you have to use option 0 and provide the Corresponding Application Code such that the user can recompile the entire program after modifying the LGPL library.

@lvella
Copy link

lvella commented Jun 27, 2023

As I understand, Section 3 covers generics and inline functions, which can be incorporated into the application object code and still be differently licensed. IANAL either, but despite using terminology of C++, I believe it also applies to Rust, as the concepts are the same.

About the unstable ABI, is there no way to compile a modified library using the same rust version so that the compatibility is guaranteed? (provided, of course, that what was changed was not inlined/monomorphized into the user's code)

@bjorn3
Copy link
Member

bjorn3 commented Jun 28, 2023

As I understand, Section 3 covers generics and inline functions, which can be incorporated into the application object code and still be differently licensed.

I see.

About the unstable ABI, is there no way to compile a modified library using the same rust version so that the compatibility is guaranteed? (provided, of course, that what was changed was not inlined/monomorphized into the user's code)

You also have to preserve the -Cmetadata argument that cargo passed to rustc for the LGPL crate and all of it's dependencies. Symbol mangling depends on it. With that it should currently be possible to swap out rust dylibs I think, but there is no guarantee and before the introduction of incr comp this indeed wouldn't work at all even with a whitespace only change. As such I did recommend actually trying if changing the source of some functions and recompiling works with every rustc version you are using.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-configuration Area: cargo config files and env vars A-linkage Area: linker issues, dylib, cdylib, shared libraries, so C-feature-request Category: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted` S-needs-info Status: Needs more info, such as a reproduction or more background for a feature request.
Projects
None yet
Development

No branches or pull requests

5 participants