Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #148 +/- ##
==========================================
- Coverage 92.64% 91.77% -0.88%
==========================================
Files 8 8
Lines 3564 3708 +144
==========================================
+ Hits 3302 3403 +101
- Misses 262 305 +43 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
The clippy warning is unrelated to this patch, it comes from updating the rust version. I submitted a fix in #149. |
433004a to
39740f1
Compare
39740f1 to
2981765
Compare
|
Your clippy fix has been merged so you can rebase this branch on top of I'll let @thiblahute review it as he's the one knowing about prebuilt binaries. |
| self.wildcards | ||
| .iter() | ||
| .find(|(prefix, provider)| { | ||
| key.starts_with(prefix.as_str()) && self.paths.contains_key(*provider) |
There was a problem hiding this comment.
Pre-existing, but now more visible: wildcards is a HashMap, so with overlapping wildcards the provider picked is nondeterministic, and it now also decides the link mode.
| /// The `cfg()` expression used in `Cargo.toml` is currently not supported | ||
| UnsupportedCfg(String), | ||
| /// Two packages provided by the same prebuilt binary resolved to different link modes | ||
| LinkModeMismatch(String, String), |
There was a problem hiding this comment.
Error isn't #[non_exhaustive], so adding a variant is a semver break. Maybe fine if the next release is a major one anyway, is that the plan @gdesmott ?
| "Internally built {s1} {s2} but minimum required version is {s3}" | ||
| ), | ||
| Self::UnsupportedCfg(s) => write!(f, "Unsupported cfg() expression: {s}"), | ||
| Self::LinkModeMismatch(name, package) => write!( |
There was a problem hiding this comment.
In this match arm the pattern variables are (name, package), but check_link_modes builds the variant as LinkModeMismatch(provider, name), so name here is really the provider -- (provider, package) would read better.
| } | ||
|
|
||
| /// Check if the dependency should be statically linked. | ||
| fn link_mode(&self, pkg: &str) -> bool { |
There was a problem hiding this comment.
It returns a bool meaning "static", so is_static() (or returning an enum) would read better than link_mode().
|
|
||
| match vars.iter().flatten().find_map(|var| self.env.get(var)) { | ||
| Some(mode) => mode == "static", | ||
| None => provider.is_some(), |
There was a problem hiding this comment.
The default comes from provider(), which ignores SYSTEM_DEPS_$NAME_NO_PREBUILT / SYSTEM_DEPS_NO_PREBUILT, while query_path() does respect them. So when a user opts a package out of the bundle, it is probed from the system but still defaults to static linking.
I reproduced it by adding this test to src/test_binary.rs on this branch, reusing the config_with() helper from the PR (the test bundle provides dep):
#[test]
fn no_prebuilt_link_mode() {
let c = config_with(HashMap::from([
("SYSTEM_DEPS_DEP_NO_PREBUILT", "1".into()),
]));
// dep is no longer served by the bundle...
assert!(c.query_path("dep").is_none());
// ...but still defaults to static: this assert fails
assert!(!c.link_mode("dep"));
}The second assert fails with cargo test --features binary.
I think the default (and the provider lookup) should be based on whether the package is actually served by the bundle, i.e. query_path(pkg).is_some(), and a test like the one above should be added.
| .skip(1) | ||
| .any(|parent| lib_dirs.iter().any(|other| other == &parent)); | ||
| if !nested { | ||
| println!("cargo:rustc-link-search=native={}", dir.display()); |
There was a problem hiding this comment.
Are these rustc-link-search lines needed? The -sys crate already emits the link paths from pkg-config, and those propagate to the final link.
|
|
||
| if rpath_origin == "$ORIGIN" { | ||
| println!( | ||
| "cargo:rustc-link-arg=-Wl,--disable-new-dtags,-rpath,{rpath_origin}/{runtime_subdir}" |
There was a problem hiding this comment.
--disable-new-dtags (forcing DT_RPATH so it also applies to transitive deps) is a deliberate choice, please add a comment explaining it.
| .cargo_metadata(false) | ||
| .range_version(metadata::parse_version(version)) | ||
| .statik(statik); | ||
| .statik(statik || prebuilt); |
There was a problem hiding this comment.
Why query pkg-config with --static for prebuilt packages even in dynamic mode? That pulls in Libs.private, so a dynamic build links every private dependency of the bundle (overlinking, and on macOS a lot more dylibs loaded at startup).
If it works around something missing in the bundle's .pc files, please add a comment; otherwise I'd expect plain .statik(statik) here.
| Ok(libraries) | ||
| } | ||
|
|
||
| fn check_link_modes(&self, libraries: &Dependencies) -> Result<(), Error> { |
There was a problem hiding this comment.
Same root cause as the link_mode() default: grouping by provider() includes packages that are no longer served by the bundle. SYSTEM_DEPS_DEP_NO_PREBUILT=1 + SYSTEM_DEPS_DEP_LINK=dynamic fails with LinkModeMismatch although dep comes from the system and cannot mix anything with the bundle.
Could you add a test for the NO_PREBUILT case as well?
|
|
||
| let testdata = libraries.get_by_name("testdata").unwrap(); | ||
| assert!(testdata.statik == cfg!(feature = "binary")); | ||
| assert!(!testdata.statik); |
There was a problem hiding this comment.
This is a behaviour change: before, enabling the binary feature made every library static, system ones included; now system libs default to dynamic. I think it's the right fix, but the PR description says it "doesn't affect the probing of system-installed libraries at all", which isn't quite true. Worth mentioning in the changelog.
Prebuilt binaries can come with static and shared libraries (gstreamer bundles come with both). The initial support for them forced static linking, but dynamic linking may be beneficial for some applications, especially when dealing with licenses. This is motivated by an experiment to support dynamic linking of gstreamer from the downloaded bundles.
This patch makes it so the
SYSTEM_DEPS_LINKenvironment variable works for prebuilt binaries too. In this case, the default remains static to avoid breaking the previous behaviour. It doesn't affect the probing of system-installed libraries at all.Note that this mode only changes how libraries are linked. Deployment is out of scope, and left entirely to the applications using
system-deps, meaning they are responsible for placing the libraries in the correct place and setting the relevant paths in the binary. We already provideConfig::query_path, which gives the path of the extracted bundle so applications can distribute it as they see fit.