Skip to content

Commit

Permalink
Initial support for using vcpkg
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
ids1024 committed Aug 26, 2020
1 parent 4b22eca commit e474492
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ heck = "0.3"
strum = "0.18"
strum_macros = "0.18"
thiserror = "1"
vcpkg = "0.2"

[dev-dependencies]
lazy_static = "1"
Expand Down
46 changes: 44 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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),
Expand Down Expand Up @@ -187,6 +191,7 @@ enum EnvVariable {
Include(String),
NoPkgConfig(String),
BuildInternal(Option<String>),
UseVcpkg(String),
}

impl EnvVariable {
Expand Down Expand Up @@ -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",
Expand All @@ -227,6 +236,7 @@ impl EnvVariable {
EnvVariable::Include(_) => "INCLUDE",
EnvVariable::NoPkgConfig(_) => "NO_PKG_CONFIG",
EnvVariable::BuildInternal(_) => "BUILD_INTERNAL",
EnvVariable::UseVcpkg(_) => "USE_VCPKG",
}
}
}
Expand All @@ -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())
}
Expand Down Expand Up @@ -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)?
Expand Down Expand Up @@ -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
))
})?;
Expand Down Expand Up @@ -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));
}
Expand All @@ -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,
}
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit e474492

Please sign in to comment.