Crate system_deps
source ·Expand description
system-deps
lets you write system dependencies in Cargo.toml
metadata,
rather than programmatically in build.rs
. This makes those dependencies
declarative, so other tools can read them as well.
§Usage
In your Cargo.toml
:
[build-dependencies]
system-deps = "2.0"
Then, to declare a dependency on testlib >= 1.2
add the following section:
[package.metadata.system-deps]
testlib = "1.2"
Finally, in your build.rs
, add:
fn main() {
system_deps::Config::new().probe().unwrap();
}
§Version format
Versions can be expressed in the following formats
- “1.2” or “>= 1.2”: At least version 1.2
- “>= 1.2, < 2.0”: At least version 1.2 but less than version 2.0
In the future more complicated version expressions might be supported.
Note that these versions are not interpreted according to the semver rules, but based on the rules defined by pkg-config.
§Feature-specific dependency
You can easily declare an optional system dependency by associating it with a feature:
[package.metadata.system-deps]
testdata = { version = "4.5", feature = "use-testdata" }
system-deps
will check for testdata
only if the use-testdata
feature has been enabled.
§Optional dependency
Another option is to use the optional
setting, which can also be used using features versions:
[package.metadata.system-deps]
test-data = { version = "4.5", optional = true }
testmore = { version = "2", v3 = { version = "3.0", optional = true }}
system-deps
will automatically export for each dependency a feature system_deps_have_$DEP
where $DEP
is the toml
key defining the dependency in snake_case.
This can be used to check if an optional dependency has been found or not:
#[cfg(system_deps_have_testdata)]
println!("found test-data");
§Overriding library name
toml
keys cannot contain dot characters so if your library name does, you can define it using the name
field:
[package.metadata.system-deps]
glib = { name = "glib-2.0", version = "2.64" }
§Fallback library names
Some libraries may be available under different names on different platforms or distributions. To allow for this, you can define fallback names to search for if the main library name does not work.
[package.metadata.system-deps]
aravis = { fallback-names = ["aravis-0.8"] }
You may also specify different fallback names for different versions:
[package.metadata.system-deps.libfoo] version = “0.1” fallback-names = [“libfoo-0.1”] v1 = { version = “1.0”, fallback-names = [“libfoo1”] } v2 = { version = “2.0”, fallback-names = [“libfoo2”] }
§Feature versions
-sys
crates willing to support various versions of their underlying system libraries
can use features to control the version of the dependency required.
system-deps
will pick the highest version among enabled features.
Such version features must use the pattern v1_0
, v1_2
, etc.
[features]
v1_2 = []
v1_4 = ["v1_2"]
v1_6 = ["v1_4"]
[package.metadata.system-deps.gstreamer_1_0]
name = "gstreamer-1.0"
version = "1.0"
v1_2 = { version = "1.2" }
v1_4 = { version = "1.4" }
v1_6 = { version = "1.6" }
The same mechanism can be used to require a different library name depending on the version:
[package.metadata.system-deps.gst_gl]
name = "gstreamer-gl-1.0"
version = "1.14"
v1_18 = { version = "1.18", name = "gstreamer-gl-egl-1.0" }
§Target specific dependencies
You can define target specific dependencies:
[package.metadata.system-deps.'cfg(target_os = "linux")']
testdata = "1"
[package.metadata.system-deps.'cfg(not(target_os = "macos"))']
testlib = "1"
[package.metadata.system-deps.'cfg(unix)']
testanotherlib = { version = "1", optional = true }
See the Rust documentation for the exact syntax. Currently, those keys are supported:
target_arch
target_endian
target_env
target_family
target_os
target_pointer_width
target_vendor
unix
andwindows
§Overriding build flags
By default system-deps
automatically defines the required build flags for each dependency using the information fetched from pkg-config
.
These flags can be overridden using environment variables if needed:
SYSTEM_DEPS_$NAME_SEARCH_NATIVE
to override thecargo:rustc-link-search=native
flag;SYSTEM_DEPS_$NAME_SEARCH_FRAMEWORK
to override thecargo:rustc-link-search=framework
flag;SYSTEM_DEPS_$NAME_LIB
to override thecargo:rustc-link-lib
flag;SYSTEM_DEPS_$NAME_LIB_FRAMEWORK
to override thecargo:rustc-link-lib=framework
flag;SYSTEM_DEPS_$NAME_INCLUDE
to override thecargo:include
flag.
With $NAME
being the upper case name of the key defining the dependency in Cargo.toml
.
For example SYSTEM_DEPS_TESTLIB_SEARCH_NATIVE=/opt/lib
could be used to override a dependency named testlib
.
One can also define the environment variable SYSTEM_DEPS_$NAME_NO_PKG_CONFIG
to fully disable pkg-config
lookup
for the given dependency. In this case at least SYSTEM_DEPS_$NAME_LIB or SYSTEM_DEPS_$NAME_LIB_FRAMEWORK should be defined as well.
§Internally build system libraries
-sys
crates can provide support for building and statically link their underlying system library as part of their build process.
Here is how to do this in your build.rs
:
fn main() {
system_deps::Config::new()
.add_build_internal("testlib", |lib, version| {
// Actually build the library here that fulfills the passed in version requirements
system_deps::Library::from_internal_pkg_config("build/path-to-pc-file", lib, "1.2.4")
})
.probe()
.unwrap();
}
This feature can be controlled using the SYSTEM_DEPS_$NAME_BUILD_INTERNAL
environment variable
which can have the following values:
auto
: build the dependency only if the required version has not been found bypkg-config
;always
: always build the dependency, ignoring any version which may be installed on the system;never
: (default) never build the dependency,system-deps
will fail if the required version is not found on the system.
You can also use the SYSTEM_DEPS_BUILD_INTERNAL
environment variable with the same values
defining the behavior for all the dependencies which don’t have SYSTEM_DEPS_$NAME_BUILD_INTERNAL
defined.
§Static linking
By default all libraries are dynamically linked, except when build internally as described above.
Libraries can be statically linked by defining the environment variable SYSTEM_DEPS_$NAME_LINK=static
.
You can also use SYSTEM_DEPS_LINK=static
to statically link all the libraries.
Structs§
- Structure used to configure
metadata
before starting to probe for dependencies - All the system dependencies retrieved by Config::probe.
- Internal library name and if a static library is available on the system
- A system dependency
Enums§
- Error used in return value of
Config::add_build_internal
closures - system-deps errors
- From where the library settings have been retrieved