|
28 | 28 | //! }
|
29 | 29 | //! ```
|
30 | 30 | //!
|
| 31 | +//! # Version format |
| 32 | +//! |
| 33 | +//! Versions can be expressed in the following formats |
| 34 | +//! |
| 35 | +//! * "1.2" or ">= 1.2": At least version 1.2 |
| 36 | +//! * ">= 1.2, < 2.0": At least version 1.2 but less than version 2.0 |
| 37 | +//! |
| 38 | +//! In the future more complicated version expressions might be supported. |
| 39 | +//! |
| 40 | +//! Note that these versions are not interpreted according to the semver rules, but based on the |
| 41 | +//! rules defined by pkg-config. |
| 42 | +//! |
31 | 43 | //! # Feature-specific dependency
|
32 | 44 | //! You can easily declare an optional system dependency by associating it with a feature:
|
33 | 45 | //!
|
|
159 | 171 | //! fn main() {
|
160 | 172 | //! system_deps::Config::new()
|
161 | 173 | //! .add_build_internal("testlib", |lib, version| {
|
162 |
| -//! // Actually build the library here |
163 |
| -//! system_deps::Library::from_internal_pkg_config("build/path-to-pc-file", lib, version) |
| 174 | +//! // Actually build the library here that fulfills the passed in version requirements |
| 175 | +//! system_deps::Library::from_internal_pkg_config("build/path-to-pc-file", lib, "1.2.4") |
164 | 176 | //! })
|
165 | 177 | //! .probe()
|
166 | 178 | //! .unwrap();
|
@@ -195,6 +207,7 @@ use heck::{ToShoutySnakeCase, ToSnakeCase};
|
195 | 207 | use std::collections::HashMap;
|
196 | 208 | use std::env;
|
197 | 209 | use std::fmt;
|
| 210 | +use std::ops::RangeBounds; |
198 | 211 | use std::path::{Path, PathBuf};
|
199 | 212 | use std::str::FromStr;
|
200 | 213 |
|
@@ -721,7 +734,18 @@ impl Config {
|
721 | 734 | optional = dep.optional;
|
722 | 735 | } else {
|
723 | 736 | enabled_feature_overrides.sort_by(|a, b| {
|
724 |
| - version_compare::compare(&a.version, &b.version) |
| 737 | + fn min_version(r: metadata::VersionRange) -> &str { |
| 738 | + match r.start_bound() { |
| 739 | + std::ops::Bound::Unbounded => unreachable!(), |
| 740 | + std::ops::Bound::Excluded(_) => unreachable!(), |
| 741 | + std::ops::Bound::Included(b) => b, |
| 742 | + } |
| 743 | + } |
| 744 | + |
| 745 | + let a = min_version(metadata::parse_version(&a.version)); |
| 746 | + let b = min_version(metadata::parse_version(&b.version)); |
| 747 | + |
| 748 | + version_compare::compare(a, b) |
725 | 749 | .expect("failed to compare versions")
|
726 | 750 | .ord()
|
727 | 751 | .expect("invalid version")
|
@@ -758,10 +782,11 @@ impl Config {
|
758 | 782 | } else {
|
759 | 783 | let mut config = pkg_config::Config::new();
|
760 | 784 | config
|
761 |
| - .atleast_version(version) |
762 | 785 | .print_system_libs(false)
|
763 | 786 | .cargo_metadata(false)
|
| 787 | + .range_version(metadata::parse_version(version)) |
764 | 788 | .statik(statik);
|
| 789 | + |
765 | 790 | match Self::probe_with_fallback(config, lib_name, fallback_lib_names) {
|
766 | 791 | Ok((lib_name, lib)) => Library::from_pkg_config(lib_name, lib),
|
767 | 792 | Err(e) => {
|
@@ -826,23 +851,55 @@ impl Config {
|
826 | 851 | }
|
827 | 852 | }
|
828 | 853 |
|
829 |
| - fn call_build_internal(&mut self, name: &str, version: &str) -> Result<Library, Error> { |
| 854 | + fn call_build_internal(&mut self, name: &str, version_str: &str) -> Result<Library, Error> { |
830 | 855 | let lib = match self.build_internals.remove(name) {
|
831 |
| - Some(f) => { |
832 |
| - f(name, version).map_err(|e| Error::BuildInternalClosureError(name.into(), e))? |
| 856 | + Some(f) => f(name, version_str) |
| 857 | + .map_err(|e| Error::BuildInternalClosureError(name.into(), e))?, |
| 858 | + None => { |
| 859 | + return Err(Error::BuildInternalNoClosure( |
| 860 | + name.into(), |
| 861 | + version_str.into(), |
| 862 | + )) |
833 | 863 | }
|
834 |
| - None => return Err(Error::BuildInternalNoClosure(name.into(), version.into())), |
835 | 864 | };
|
836 | 865 |
|
837 | 866 | // Check that the lib built internally matches the required version
|
838 |
| - match version_compare::compare(&lib.version, version) { |
839 |
| - Ok(version_compare::Cmp::Lt) => Err(Error::BuildInternalWrongVersion( |
| 867 | + let version = metadata::parse_version(version_str); |
| 868 | + fn min_version(r: metadata::VersionRange) -> &str { |
| 869 | + match r.start_bound() { |
| 870 | + std::ops::Bound::Unbounded => unreachable!(), |
| 871 | + std::ops::Bound::Excluded(_) => unreachable!(), |
| 872 | + std::ops::Bound::Included(b) => b, |
| 873 | + } |
| 874 | + } |
| 875 | + fn max_version(r: metadata::VersionRange) -> Option<&str> { |
| 876 | + match r.end_bound() { |
| 877 | + std::ops::Bound::Included(_) => unreachable!(), |
| 878 | + std::ops::Bound::Unbounded => None, |
| 879 | + std::ops::Bound::Excluded(b) => Some(*b), |
| 880 | + } |
| 881 | + } |
| 882 | + |
| 883 | + let min = min_version(version.clone()); |
| 884 | + if version_compare::compare(&lib.version, min) == Ok(version_compare::Cmp::Lt) { |
| 885 | + return Err(Error::BuildInternalWrongVersion( |
840 | 886 | name.into(),
|
841 | 887 | lib.version,
|
842 |
| - version.into(), |
843 |
| - )), |
844 |
| - _ => Ok(lib), |
| 888 | + version_str.into(), |
| 889 | + )); |
845 | 890 | }
|
| 891 | + |
| 892 | + if let Some(max) = max_version(version) { |
| 893 | + if version_compare::compare(&lib.version, max) == Ok(version_compare::Cmp::Ge) { |
| 894 | + return Err(Error::BuildInternalWrongVersion( |
| 895 | + name.into(), |
| 896 | + lib.version, |
| 897 | + version_str.into(), |
| 898 | + )); |
| 899 | + } |
| 900 | + } |
| 901 | + |
| 902 | + Ok(lib) |
846 | 903 | }
|
847 | 904 |
|
848 | 905 | fn has_feature(&self, feature: &str) -> bool {
|
@@ -1008,9 +1065,9 @@ impl Library {
|
1008 | 1065 | /// ```
|
1009 | 1066 | /// let mut config = system_deps::Config::new();
|
1010 | 1067 | /// config.add_build_internal("mylib", |lib, version| {
|
1011 |
| - /// // Actually build the library here |
| 1068 | + /// // Actually build the library here that fulfills the passed in version requirements |
1012 | 1069 | /// system_deps::Library::from_internal_pkg_config("build-dir",
|
1013 |
| - /// lib, version) |
| 1070 | + /// lib, "1.2.4") |
1014 | 1071 | /// });
|
1015 | 1072 | /// ```
|
1016 | 1073 | pub fn from_internal_pkg_config<P>(
|
|
0 commit comments