From e474492e98e196775591c9fa36d55aa826f1f865 Mon Sep 17 00:00:00 2001 From: Ian Douglas Scott Date: Mon, 24 Aug 2020 16:32:54 -0700 Subject: [PATCH] Initial support for using vcpkg This seems to be the favored way for finding libraries under msvc, and the `vcpkg` crate is a reverse dependency of various -sys crates. It seems to have some issues as is. Vcpkg doesn't seem to have support for finding a particular version of a package. And with this, `glib-sys`, for instance, still fails to build without changes because it needs to search for just `glib`, not `glib-2.0`. Perhaps the solution is to add an optional `vcpkg_name` that can be specified in toml? But in any case, this shows what's involved in supporting vcpkg. --- Cargo.toml | 1 + src/lib.rs | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5f3ab0d..2b38d10 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ heck = "0.3" strum = "0.18" strum_macros = "0.18" thiserror = "1" +vcpkg = "0.2" [dev-dependencies] lazy_static = "1" diff --git a/src/lib.rs b/src/lib.rs index 5b465ab..4baa98e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -116,6 +116,7 @@ use std::str::FromStr; use strum::IntoEnumIterator; use strum_macros::{EnumIter, EnumString}; use thiserror::Error; +use vcpkg; use version_compare::VersionCompare; /// system-deps errors @@ -124,6 +125,9 @@ pub enum Error { /// pkg-config error #[error(transparent)] PkgConfig(#[from] pkg_config::Error), + /// vcpkg error + #[error(transparent)] + Vcpkg(#[from] vcpkg::Error), /// One of the `Config::add_build_internal` closures failed #[error("Failed to build {0}: {1}")] BuildInternalClosureError(String, #[source] BuildInternalClosureError), @@ -187,6 +191,7 @@ enum EnvVariable { Include(String), NoPkgConfig(String), BuildInternal(Option), + UseVcpkg(String), } impl EnvVariable { @@ -218,6 +223,10 @@ impl EnvVariable { Self::BuildInternal(lib.map(|l| l.to_string())) } + fn new_use_vcpkg(lib: &str) -> Self { + Self::UseVcpkg(lib.to_string()) + } + fn suffix(&self) -> &'static str { match self { EnvVariable::Lib(_) => "LIB", @@ -227,6 +236,7 @@ impl EnvVariable { EnvVariable::Include(_) => "INCLUDE", EnvVariable::NoPkgConfig(_) => "NO_PKG_CONFIG", EnvVariable::BuildInternal(_) => "BUILD_INTERNAL", + EnvVariable::UseVcpkg(_) => "USE_VCPKG", } } } @@ -240,6 +250,7 @@ impl fmt::Display for EnvVariable { | EnvVariable::SearchFramework(lib) | EnvVariable::Include(lib) | EnvVariable::NoPkgConfig(lib) + | EnvVariable::UseVcpkg(lib) | EnvVariable::BuildInternal(Some(lib)) => { format!("{}_{}", lib.to_shouty_snake_case(), self.suffix()) } @@ -436,7 +447,22 @@ impl Config { let build_internal = self.get_build_internal_status(name)?; - let library = if self.env.contains(&EnvVariable::new_no_pkg_config(name)) { + let library = if self.env.contains(&EnvVariable::new_use_vcpkg(name)) { + match vcpkg::Config::new() + .cargo_metadata(false) + .find_package(lib_name) + { + Ok(lib) => Library::from_vcpkg(lib), + Err(e) => { + if build_internal == BuildInternal::Auto { + // Try building the lib internally as a fallback + self.call_build_internal(name, version)? + } else { + return Err(e.into()); + } + } + } + } else if self.env.contains(&EnvVariable::new_no_pkg_config(name)) { Library::from_env_variables() } else if build_internal == BuildInternal::Always { self.call_build_internal(lib_name, version)? @@ -469,7 +495,7 @@ impl Config { Some(s) => { let b = BuildInternal::from_str(s).map_err(|_| { Error::BuildInternalInvalid(format!( - "Invalid value in {}: {} (allowed: 'auto', 'always', 'never')", + "Invalid value in {}: {} (allowed: 'auto', 'always', 'nzever')", var, s )) })?; @@ -578,6 +604,7 @@ impl Config { EnvVariable::Include(_) => EnvVariable::new_include(name), EnvVariable::NoPkgConfig(_) => EnvVariable::new_no_pkg_config(name), EnvVariable::BuildInternal(_) => EnvVariable::new_build_internal(Some(name)), + EnvVariable::UseVcpkg(_) => EnvVariable::new_use_vcpkg(name), }; flags.add(BuildFlag::RerunIfEnvChanged(var)); } @@ -597,6 +624,8 @@ impl Config { pub enum Source { /// Settings have been retrieved from `pkg-config` PkgConfig, + /// Settings have been retrieved from `vcpkg` + Vcpkg, /// Settings have been defined using user defined environment variables EnvVariables, } @@ -636,6 +665,19 @@ impl Library { } } + fn from_vcpkg(l: vcpkg::Library) -> Self { + Self { + source: Source::Vcpkg, + libs: l.found_names, + link_paths: l.link_paths, + include_paths: l.include_paths, + frameworks: Vec::new(), + framework_paths: Vec::new(), + defines: HashMap::new(), + version: String::new(), + } + } + fn from_env_variables() -> Self { Self { source: Source::EnvVariables,