//! A build dependency for Cargo libraries to find system artifacts through the
//! `pkg-config` utility.
//!
//! This library will shell out to `pkg-config` as part of build scripts and
//! probe the system to determine how to link to a specified library. The
//! `Config` structure serves as a method of configuring how `pkg-config` is
//! invoked in a builder style.
//!
//! A number of environment variables are available to globally configure how
//! this crate will invoke `pkg-config`:
//!
//! * `FOO_NO_PKG_CONFIG` - if set, this will disable running `pkg-config` when
//!   probing for the library named `foo`.
//!
//! * `PKG_CONFIG_ALLOW_CROSS` - The `pkg-config` command usually doesn't
//!   support cross-compilation, and this crate prevents it from selecting
//!   incompatible versions of libraries.
//!   Setting `PKG_CONFIG_ALLOW_CROSS=1` disables this protection, which is
//!   likely to cause linking errors, unless `pkg-config` has been configured
//!   to use appropriate sysroot and search paths for the target platform.
//!
//! There are also a number of environment variables which can configure how a
//! library is linked to (dynamically vs statically). These variables control
//! whether the `--static` flag is passed. Note that this behavior can be
//! overridden by configuring explicitly on `Config`. The variables are checked
//! in the following order:
//!
//! * `FOO_STATIC` - pass `--static` for the library `foo`
//! * `FOO_DYNAMIC` - do not pass `--static` for the library `foo`
//! * `PKG_CONFIG_ALL_STATIC` - pass `--static` for all libraries
//! * `PKG_CONFIG_ALL_DYNAMIC` - do not pass `--static` for all libraries
//!
//! After running `pkg-config` all appropriate Cargo metadata will be printed on
//! stdout if the search was successful.
//!
//! # Example
//!
//! Find the system library named `foo`, with minimum version 1.2.3:
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::Config::new().atleast_version("1.2.3").probe("foo").unwrap();
//! }
//! ```
//!
//! Find the system library named `foo`, with no version requirement (not
//! recommended):
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::probe_library("foo").unwrap();
//! }
//! ```
//!
//! Configure how library `foo` is linked to.
//!
//! ```no_run
//! extern crate pkg_config;
//!
//! fn main() {
//!     pkg_config::Config::new().atleast_version("1.2.3").statik(true).probe("foo").unwrap();
//! }
//! ```

#![doc(html_root_url = "https://docs.rs/pkg-config/0.3")]

use std::collections::HashMap;
use std::env;
use std::error;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::io;
use std::ops::{Bound, RangeBounds};
use std::path::PathBuf;
use std::process::{Command, Output};
use std::str;

#[derive(Clone, Debug)]
pub struct Config {
    statik: Option<bool>,
    min_version: Bound<String>,
    max_version: Bound<String>,
    extra_args: Vec<OsString>,
    cargo_metadata: bool,
    env_metadata: bool,
    print_system_libs: bool,
    print_system_cflags: bool,
}

#[derive(Clone, Debug)]
pub struct Library {
    pub libs: Vec<String>,
    pub link_paths: Vec<PathBuf>,
    pub frameworks: Vec<String>,
    pub framework_paths: Vec<PathBuf>,
    pub include_paths: Vec<PathBuf>,
    pub defines: HashMap<String, Option<String>>,
    pub version: String,
    _priv: (),
}

/// Represents all reasons `pkg-config` might not succeed or be run at all.
#[derive(Debug)]
pub enum Error {
    /// Aborted because of `*_NO_PKG_CONFIG` environment variable.
    ///
    /// Contains the name of the responsible environment variable.
    EnvNoPkgConfig(String),

    /// Detected cross compilation without a custom sysroot.
    ///
    /// Ignore the error with `PKG_CONFIG_ALLOW_CROSS=1`,
    /// which may let `pkg-config` select libraries
    /// for the host's architecture instead of the target's.
    CrossCompilation,

    /// Failed to run `pkg-config`.
    ///
    /// Contains the command and the cause.
    Command { command: String, cause: io::Error },

    /// `pkg-config` did not exit sucessfully.
    ///
    /// Contains the command and output.
    Failure { command: String, output: Output },

    #[doc(hidden)]
    // please don't match on this, we're likely to add more variants over time
    __Nonexhaustive,
}

impl error::Error for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::EnvNoPkgConfig(ref name) => write!(f, "Aborted because {} is set", name),
            Error::CrossCompilation => f.write_str(
                "pkg-config has not been configured to support cross-compilation.

                Install a sysroot for the target platform and configure it via
                PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a
                cross-compiling wrapper for pkg-config and set it via
                PKG_CONFIG environment variable.",
            ),
            Error::Command {
                ref command,
                ref cause,
            } => write!(f, "Failed to run `{}`: {}", command, cause),
            Error::Failure {
                ref command,
                ref output,
            } => {
                let stdout = str::from_utf8(&output.stdout).unwrap();
                let stderr = str::from_utf8(&output.stderr).unwrap();
                write!(
                    f,
                    "`{}` did not exit successfully: {}",
                    command, output.status
                )?;
                if !stdout.is_empty() {
                    write!(f, "\n--- stdout\n{}", stdout)?;
                }
                if !stderr.is_empty() {
                    write!(f, "\n--- stderr\n{}", stderr)?;
                }
                Ok(())
            }
            Error::__Nonexhaustive => panic!(),
        }
    }
}

/// Deprecated in favor of the probe_library function
#[doc(hidden)]
pub fn find_library(name: &str) -> Result<Library, String> {
    probe_library(name).map_err(|e| e.to_string())
}

/// Simple shortcut for using all default options for finding a library.
pub fn probe_library(name: &str) -> Result<Library, Error> {
    Config::new().probe(name)
}

/// Run `pkg-config` to get the value of a variable from a package using
/// `--variable`.
///
/// The content of `PKG_CONFIG_SYSROOT_DIR` is not injected in paths that are
/// returned by `pkg-config --variable`, which makes them unsuitable to use
/// during cross-compilation unless specifically designed to be used
/// at that time.
pub fn get_variable(package: &str, variable: &str) -> Result<String, Error> {
    let arg = format!("--variable={}", variable);
    let cfg = Config::new();
    let out = run(cfg.command(package, &[&arg]))?;
    Ok(str::from_utf8(&out).unwrap().trim_end().to_owned())
}

impl Config {
    /// Creates a new set of configuration options which are all initially set
    /// to "blank".
    pub fn new() -> Config {
        Config {
            statik: None,
            min_version: Bound::Unbounded,
            max_version: Bound::Unbounded,
            extra_args: vec![],
            print_system_cflags: true,
            print_system_libs: true,
            cargo_metadata: true,
            env_metadata: true,
        }
    }

    /// Indicate whether the `--static` flag should be passed.
    ///
    /// This will override the inference from environment variables described in
    /// the crate documentation.
    pub fn statik(&mut self, statik: bool) -> &mut Config {
        self.statik = Some(statik);
        self
    }

    /// Indicate that the library must be at least version `vers`.
    pub fn atleast_version(&mut self, vers: &str) -> &mut Config {
        self.min_version = Bound::Included(vers.to_string());
        self.max_version = Bound::Unbounded;
        self
    }

    /// Indicate that the library must be equal to version `vers`.
    pub fn exactly_version(&mut self, vers: &str) -> &mut Config {
        self.min_version = Bound::Included(vers.to_string());
        self.max_version = Bound::Included(vers.to_string());
        self
    }

    /// Indicate that the library's version must be in `range`.
    pub fn range_version<'a, R>(&mut self, range: R) -> &mut Config
    where
        R: RangeBounds<&'a str>,
    {
        self.min_version = match range.start_bound() {
            Bound::Included(vers) => Bound::Included(vers.to_string()),
            Bound::Excluded(vers) => Bound::Excluded(vers.to_string()),
            Bound::Unbounded => Bound::Unbounded,
        };
        self.max_version = match range.end_bound() {
            Bound::Included(vers) => Bound::Included(vers.to_string()),
            Bound::Excluded(vers) => Bound::Excluded(vers.to_string()),
            Bound::Unbounded => Bound::Unbounded,
        };
        self
    }

    /// Add an argument to pass to pkg-config.
    ///
    /// It's placed after all of the arguments generated by this library.
    pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Config {
        self.extra_args.push(arg.as_ref().to_os_string());
        self
    }

    /// Define whether metadata should be emitted for cargo allowing it to
    /// automatically link the binary. Defaults to `true`.
    pub fn cargo_metadata(&mut self, cargo_metadata: bool) -> &mut Config {
        self.cargo_metadata = cargo_metadata;
        self
    }

    /// Define whether metadata should be emitted for cargo allowing to
    /// automatically rebuild when environment variables change. Defaults to
    /// `true`.
    pub fn env_metadata(&mut self, env_metadata: bool) -> &mut Config {
        self.env_metadata = env_metadata;
        self
    }

    /// Enable or disable the `PKG_CONFIG_ALLOW_SYSTEM_LIBS` environment
    /// variable.
    ///
    /// This env var is enabled by default.
    pub fn print_system_libs(&mut self, print: bool) -> &mut Config {
        self.print_system_libs = print;
        self
    }

    /// Enable or disable the `PKG_CONFIG_ALLOW_SYSTEM_CFLAGS` environment
    /// variable.
    ///
    /// This env var is enabled by default.
    pub fn print_system_cflags(&mut self, print: bool) -> &mut Config {
        self.print_system_cflags = print;
        self
    }

    /// Deprecated in favor fo the `probe` function
    #[doc(hidden)]
    pub fn find(&self, name: &str) -> Result<Library, String> {
        self.probe(name).map_err(|e| e.to_string())
    }

    /// Run `pkg-config` to find the library `name`.
    ///
    /// This will use all configuration previously set to specify how
    /// `pkg-config` is run.
    pub fn probe(&self, name: &str) -> Result<Library, Error> {
        let abort_var_name = format!("{}_NO_PKG_CONFIG", envify(name));
        if self.env_var_os(&abort_var_name).is_some() {
            return Err(Error::EnvNoPkgConfig(abort_var_name));
        } else if !self.target_supported() {
            return Err(Error::CrossCompilation);
        }

        let mut library = Library::new();

        let output = run(self.command(name, &["--libs", "--cflags"]))?;
        library.parse_libs_cflags(name, &output, self);

        let output = run(self.command(name, &["--modversion"]))?;
        library.parse_modversion(str::from_utf8(&output).unwrap());

        Ok(library)
    }

    pub fn target_supported(&self) -> bool {
        let target = env::var_os("TARGET").unwrap_or_default();
        let host = env::var_os("HOST").unwrap_or_default();

        // Only use pkg-config in host == target situations by default (allowing an
        // override).
        if host == target {
            return true;
        }

        // pkg-config may not be aware of cross-compilation, and require
        // a wrapper script that sets up platform-specific prefixes.
        match self.targetted_env_var("PKG_CONFIG_ALLOW_CROSS") {
            // don't use pkg-config if explicitly disabled
            Some(ref val) if val == "0" => false,
            Some(_) => true,
            None => {
                // if not disabled, and pkg-config is customized,
                // then assume it's prepared for cross-compilation
                self.targetted_env_var("PKG_CONFIG").is_some()
                    || self.targetted_env_var("PKG_CONFIG_SYSROOT_DIR").is_some()
            }
        }
    }

    /// Deprecated in favor of the top level `get_variable` function
    #[doc(hidden)]
    pub fn get_variable(package: &str, variable: &str) -> Result<String, String> {
        get_variable(package, variable).map_err(|e| e.to_string())
    }

    fn targetted_env_var(&self, var_base: &str) -> Option<OsString> {
        match (env::var("TARGET"), env::var("HOST")) {
            (Ok(target), Ok(host)) => {
                let kind = if host == target { "HOST" } else { "TARGET" };
                let target_u = target.replace("-", "_");

                self.env_var_os(&format!("{}_{}", var_base, target))
                    .or_else(|| self.env_var_os(&format!("{}_{}", var_base, target_u)))
                    .or_else(|| self.env_var_os(&format!("{}_{}", kind, var_base)))
                    .or_else(|| self.env_var_os(var_base))
            }
            (Err(env::VarError::NotPresent), _) | (_, Err(env::VarError::NotPresent)) => {
                self.env_var_os(var_base)
            }
            (Err(env::VarError::NotUnicode(s)), _) | (_, Err(env::VarError::NotUnicode(s))) => {
                panic!(
                    "HOST or TARGET environment variable is not valid unicode: {:?}",
                    s
                )
            }
        }
    }

    fn env_var_os(&self, name: &str) -> Option<OsString> {
        if self.env_metadata {
            println!("cargo:rerun-if-env-changed={}", name);
        }
        env::var_os(name)
    }

    fn is_static(&self, name: &str) -> bool {
        self.statik.unwrap_or_else(|| self.infer_static(name))
    }

    fn command(&self, name: &str, args: &[&str]) -> Command {
        let exe = self
            .env_var_os("PKG_CONFIG")
            .unwrap_or_else(|| OsString::from("pkg-config"));
        let mut cmd = Command::new(exe);
        if self.is_static(name) {
            cmd.arg("--static");
        }
        cmd.args(args).args(&self.extra_args);

        if let Some(value) = self.targetted_env_var("PKG_CONFIG_PATH") {
            cmd.env("PKG_CONFIG_PATH", value);
        }
        if let Some(value) = self.targetted_env_var("PKG_CONFIG_LIBDIR") {
            cmd.env("PKG_CONFIG_LIBDIR", value);
        }
        if let Some(value) = self.targetted_env_var("PKG_CONFIG_SYSROOT_DIR") {
            cmd.env("PKG_CONFIG_SYSROOT_DIR", value);
        }
        if self.print_system_libs {
            cmd.env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1");
        }
        if self.print_system_cflags {
            cmd.env("PKG_CONFIG_ALLOW_SYSTEM_CFLAGS", "1");
        }
        cmd.arg(name);
        match self.min_version {
            Bound::Included(ref version) => {
                cmd.arg(&format!("{} >= {}", name, version));
            }
            Bound::Excluded(ref version) => {
                cmd.arg(&format!("{} > {}", name, version));
            }
            _ => (),
        }
        match self.max_version {
            Bound::Included(ref version) => {
                cmd.arg(&format!("{} <= {}", name, version));
            }
            Bound::Excluded(ref version) => {
                cmd.arg(&format!("{} < {}", name, version));
            }
            _ => (),
        }
        cmd
    }

    fn print_metadata(&self, s: &str) {
        if self.cargo_metadata {
            println!("cargo:{}", s);
        }
    }

    fn infer_static(&self, name: &str) -> bool {
        let name = envify(name);
        if self.env_var_os(&format!("{}_STATIC", name)).is_some() {
            true
        } else if self.env_var_os(&format!("{}_DYNAMIC", name)).is_some() {
            false
        } else if self.env_var_os("PKG_CONFIG_ALL_STATIC").is_some() {
            true
        } else if self.env_var_os("PKG_CONFIG_ALL_DYNAMIC").is_some() {
            false
        } else {
            false
        }
    }
}

// Implement Default manualy since Bound does not implement Default.
impl Default for Config {
    fn default() -> Config {
        Config {
            statik: None,
            min_version: Bound::Unbounded,
            max_version: Bound::Unbounded,
            extra_args: vec![],
            print_system_cflags: false,
            print_system_libs: false,
            cargo_metadata: false,
            env_metadata: false,
        }
    }
}

impl Library {
    fn new() -> Library {
        Library {
            libs: Vec::new(),
            link_paths: Vec::new(),
            include_paths: Vec::new(),
            frameworks: Vec::new(),
            framework_paths: Vec::new(),
            defines: HashMap::new(),
            version: String::new(),
            _priv: (),
        }
    }

    fn parse_libs_cflags(&mut self, name: &str, output: &[u8], config: &Config) {
        let mut is_msvc = false;
        if let Ok(target) = env::var("TARGET") {
            if target.contains("msvc") {
                is_msvc = true;
            }
        }

        let system_roots = if cfg!(target_os = "macos") {
            vec![PathBuf::from("/Library"), PathBuf::from("/System")]
        } else {
            let sysroot = config
                .env_var_os("PKG_CONFIG_SYSROOT_DIR")
                .or_else(|| config.env_var_os("SYSROOT"))
                .map(PathBuf::from);

            if cfg!(target_os = "windows") {
                if let Some(sysroot) = sysroot {
                    vec![sysroot]
                } else {
                    vec![]
                }
            } else {
                vec![sysroot.unwrap_or_else(|| PathBuf::from("/usr"))]
            }
        };

        let mut dirs = Vec::new();
        let statik = config.is_static(name);

        let words = split_flags(output);

        // Handle single-character arguments like `-I/usr/include`
        let parts = words
            .iter()
            .filter(|l| l.len() > 2)
            .map(|arg| (&arg[0..2], &arg[2..]));
        for (flag, val) in parts {
            match flag {
                "-L" => {
                    let meta = format!("rustc-link-search=native={}", val);
                    config.print_metadata(&meta);
                    dirs.push(PathBuf::from(val));
                    self.link_paths.push(PathBuf::from(val));
                }
                "-F" => {
                    let meta = format!("rustc-link-search=framework={}", val);
                    config.print_metadata(&meta);
                    self.framework_paths.push(PathBuf::from(val));
                }
                "-I" => {
                    self.include_paths.push(PathBuf::from(val));
                }
                "-l" => {
                    // These are provided by the CRT with MSVC
                    if is_msvc && ["m", "c", "pthread"].contains(&val) {
                        continue;
                    }

                    if statik && is_static_available(val, &system_roots, &dirs) {
                        let meta = format!("rustc-link-lib=static={}", val);
                        config.print_metadata(&meta);
                    } else {
                        let meta = format!("rustc-link-lib={}", val);
                        config.print_metadata(&meta);
                    }

                    self.libs.push(val.to_string());
                }
                "-D" => {
                    let mut iter = val.split('=');
                    self.defines.insert(
                        iter.next().unwrap().to_owned(),
                        iter.next().map(|s| s.to_owned()),
                    );
                }
                _ => {}
            }
        }

        // Handle multi-character arguments with space-separated value like `-framework foo`
        let mut iter = words.iter().flat_map(|arg| {
            if arg.starts_with("-Wl,") {
                arg[4..].split(',').collect()
            } else {
                vec![arg.as_ref()]
            }
        });
        while let Some(part) = iter.next() {
            match part {
                "-framework" => {
                    if let Some(lib) = iter.next() {
                        let meta = format!("rustc-link-lib=framework={}", lib);
                        config.print_metadata(&meta);
                        self.frameworks.push(lib.to_string());
                    }
                }
                "-isystem" | "-iquote" | "-idirafter" => {
                    if let Some(inc) = iter.next() {
                        self.include_paths.push(PathBuf::from(inc));
                    }
                }
                _ => (),
            }
        }
    }

    fn parse_modversion(&mut self, output: &str) {
        self.version.push_str(output.lines().nth(0).unwrap().trim());
    }
}

fn envify(name: &str) -> String {
    name.chars()
        .map(|c| c.to_ascii_uppercase())
        .map(|c| if c == '-' { '_' } else { c })
        .collect()
}

/// System libraries should only be linked dynamically
fn is_static_available(name: &str, system_roots: &[PathBuf], dirs: &[PathBuf]) -> bool {
    let libname = format!("lib{}.a", name);

    dirs.iter().any(|dir| {
        !system_roots.iter().any(|sys| dir.starts_with(sys)) && dir.join(&libname).exists()
    })
}

fn run(mut cmd: Command) -> Result<Vec<u8>, Error> {
    match cmd.output() {
        Ok(output) => {
            if output.status.success() {
                Ok(output.stdout)
            } else {
                Err(Error::Failure {
                    command: format!("{:?}", cmd),
                    output,
                })
            }
        }
        Err(cause) => Err(Error::Command {
            command: format!("{:?}", cmd),
            cause,
        }),
    }
}

/// Split output produced by pkg-config --cflags and / or --libs into separate flags.
///
/// Backslash in output is used to preserve literal meaning of following byte.  Different words are
/// separated by unescaped space. Other whitespace characters generally should not occur unescaped
/// at all, apart from the newline at the end of output. For compatibility with what others
/// consumers of pkg-config output would do in this scenario, they are used here for splitting as
/// well.
fn split_flags(output: &[u8]) -> Vec<String> {
    let mut word = Vec::new();
    let mut words = Vec::new();
    let mut escaped = false;

    for &b in output {
        match b {
            _ if escaped => {
                escaped = false;
                word.push(b);
            }
            b'\\' => escaped = true,
            b'\t' | b'\n' | b'\r' | b' ' => {
                if !word.is_empty() {
                    words.push(String::from_utf8(word).unwrap());
                    word = Vec::new();
                }
            }
            _ => word.push(b),
        }
    }

    if !word.is_empty() {
        words.push(String::from_utf8(word).unwrap());
    }

    words
}

#[test]
#[cfg(target_os = "macos")]
fn system_library_mac_test() {
    let system_roots = vec![PathBuf::from("/Library"), PathBuf::from("/System")];

    assert!(!is_static_available(
        "PluginManager",
        system_roots,
        &[PathBuf::from("/Library/Frameworks")]
    ));
    assert!(!is_static_available(
        "python2.7",
        system_roots,
        &[PathBuf::from(
            "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/config"
        )]
    ));
    assert!(!is_static_available(
        "ffi_convenience",
        system_roots,
        &[PathBuf::from(
            "/Library/Ruby/Gems/2.0.0/gems/ffi-1.9.10/ext/ffi_c/libffi-x86_64/.libs"
        )]
    ));

    // Homebrew is in /usr/local, and it's not a part of the OS
    if Path::new("/usr/local/lib/libpng16.a").exists() {
        assert!(is_static_available(
            "png16",
            system_roots,
            &[PathBuf::from("/usr/local/lib")]
        ));

        let libpng = Config::new()
            .range_version("1".."99")
            .probe("libpng16")
            .unwrap();
        assert!(libpng.version.find('\n').is_none());
    }
}

#[test]
#[cfg(target_os = "linux")]
fn system_library_linux_test() {
    assert!(!is_static_available(
        "util",
        &[PathBuf::from("/usr")],
        &[PathBuf::from("/usr/lib/x86_64-linux-gnu")]
    ));
    assert!(!is_static_available(
        "dialog",
        &[PathBuf::from("/usr")],
        &[PathBuf::from("/usr/lib")]
    ));
}
