[librsvg: 2/3] Express system dependencies using the system_deps crate




commit 6268aaa0aa1378c1e6561bacdcc8b8b1ae45bb12
Author: Sven Neumann <sven svenfoo org>
Date:   Thu Mar 18 19:21:54 2021 +0100

    Express system dependencies using the system_deps crate
    
    Kudos to the system_deps devs for implementing and swiftly
    releasing the features we needed to make this work.
    
    Fixes !675

 Cargo.lock                        | 103 +++++++++++++++++++++++++++++++++++++-
 Cargo.toml                        |  26 +++++++++-
 build.rs                          |  98 ++----------------------------------
 src/bin/rsvg-convert.rs           |  32 ++++++------
 tests/build.rs                    |  15 ------
 tests/src/cmdline/rsvg_convert.rs |  26 +++++-----
 tests/src/utils.rs                |   6 +--
 7 files changed, 163 insertions(+), 143 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 91cf2a35..31700d83 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -30,6 +30,12 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "anyhow"
+version = "1.0.38"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1"
+
 [[package]]
 name = "approx"
 version = "0.3.2"
@@ -167,6 +173,15 @@ dependencies = [
  "rustc_version",
 ]
 
+[[package]]
+name = "cfg-expr"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "30aa9e2ffbb838c6b451db14f3cd8e63ed622bf859f9956bc93845a10fafc26a"
+dependencies = [
+ "smallvec",
+]
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -748,6 +763,15 @@ version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3"
 
+[[package]]
+name = "heck"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac"
+dependencies = [
+ "unicode-segmentation",
+]
+
 [[package]]
 name = "hermit-abi"
 version = "0.1.18"
@@ -861,7 +885,6 @@ dependencies = [
  "pango",
  "pango-sys",
  "pangocairo",
- "pkg-config",
  "png",
  "predicates",
  "proptest",
@@ -871,6 +894,7 @@ dependencies = [
  "rgb",
  "selectors",
  "string_cache",
+ "system-deps",
  "tempfile",
  "test-generator",
  "tinyvec 0.3.4",
@@ -1912,6 +1936,24 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
 
+[[package]]
+name = "strum"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
+
+[[package]]
+name = "strum_macros"
+version = "0.20.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
+dependencies = [
+ "heck",
+ "proc-macro2 1.0.24",
+ "quote 1.0.9",
+ "syn 1.0.63",
+]
+
 [[package]]
 name = "syn"
 version = "0.15.44"
@@ -1934,6 +1976,24 @@ dependencies = [
  "unicode-xid 0.2.1",
 ]
 
+[[package]]
+name = "system-deps"
+version = "3.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "0fbb68eac6404c4c357c4a9a0d6395b82c753815d4bc0c4e3114a97b035c6459"
+dependencies = [
+ "anyhow",
+ "cfg-expr",
+ "heck",
+ "itertools 0.10.0",
+ "pkg-config",
+ "strum",
+ "strum_macros",
+ "thiserror",
+ "toml",
+ "version-compare",
+]
+
 [[package]]
 name = "tempfile"
 version = "3.2.0"
@@ -1986,6 +2046,26 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
 
+[[package]]
+name = "thiserror"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.23"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
+dependencies = [
+ "proc-macro2 1.0.24",
+ "quote 1.0.9",
+ "syn 1.0.63",
+]
+
 [[package]]
 name = "thread_local"
 version = "1.1.3"
@@ -2074,6 +2154,15 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
+[[package]]
+name = "toml"
+version = "0.5.8"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "treeline"
 version = "0.1.0"
@@ -2104,6 +2193,12 @@ dependencies = [
  "tinyvec 1.1.1",
 ]
 
+[[package]]
+name = "unicode-segmentation"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+
 [[package]]
 name = "unicode-width"
 version = "0.1.8"
@@ -2146,6 +2241,12 @@ version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
 
+[[package]]
+name = "version-compare"
+version = "0.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "1c18c859eead79d8b95d09e4678566e8d70105c4e7b251f707a03df32442661b"
+
 [[package]]
 name = "version_check"
 version = "0.9.2"
diff --git a/Cargo.toml b/Cargo.toml
index 84152e52..2e806ab7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -5,6 +5,29 @@ authors = ["Federico Mena Quintero <federico gnome org>"]
 build = "build.rs"
 edition = "2018"
 
+[package.metadata.system-deps]
+cairo = "1.16"
+cairo-gobject = "1.16"
+cairo-pdf = { version = "1.16", optional = true }
+cairo-png = "1.16"
+cairo-ps = { version = "1.16", optional = true }
+cairo-svg = { version = "1.16", optional = true }
+freetype2 = "20.0.14"
+gdk-pixbuf = { name = "gdk-pixbuf-2.0", version = "2.20" }
+gio = { name = "gio-2.0", version = "2.24" }
+glib = { name = "glib-2.0", version = "2.50" }
+harfbuzz = "2.0"
+libxml2 = { name = "libxml-2.0", version = "2.9" }
+pangocairo = "1.38"
+
+[package.metadata.system-deps.'cfg(windows)']
+fontconfig = { version = "1.7", optional = true }
+pangoft2 = { version = "1.38", optional = true }
+
+[package.metadata.system-deps.'cfg(not(windows))']
+fontconfig = { version = "1.7" }
+pangoft2 = { version = "1.38" }
+
 [lib]
 name = "librsvg"
 crate-type = [ "staticlib", "rlib" ]
@@ -60,7 +83,6 @@ glib = "0.9.0"
 libc = "0.2"
 lopdf = "0.26.0"
 matches = "0.1"
-pkg-config = "0.3.14"
 pango = "0.8.0"
 pango-sys = "0.9.0"
 pangocairo = "0.9.0"
@@ -72,8 +94,8 @@ test-generator = "0.3"
 yeslogic-fontconfig-sys = "2.11.1"
 
 [build-dependencies]
-pkg-config = "0.3.14"
 regex = "1.3.9"
+system-deps = "3.1"
 
 [[bench]]
 name = "box_blur"
diff --git a/build.rs b/build.rs
index 25ffaa9b..41d5a8ac 100644
--- a/build.rs
+++ b/build.rs
@@ -2,106 +2,18 @@ use regex::Regex;
 use std::env;
 use std::fs::File;
 use std::io::prelude::*;
-use std::io::{self, BufReader, BufWriter, Write};
+use std::io::{BufReader, BufWriter, Write};
 use std::path::Path;
 use std::process;
 
-use pkg_config::{Config, Error};
-
-const CAIRO_REQUIRED_VERSION: &str = "1.16";
-const PANGO_REQUIRED_VERSION: &str = "1.38";
-const LIBXML_REQUIRED_VERSION: &str = "2.9.0";
-
 fn main() {
-    find_libxml2();
-    check_for_pangoft2();
-    check_for_cairo_surface_backends();
-    generate_srgb_tables();
-    write_version();
-}
-
-fn find_libxml2() {
-    if let Err(s) = find("libxml-2.0", LIBXML_REQUIRED_VERSION, &["xml2"]) {
-        let _ = writeln!(io::stderr(), "{}", s);
+    if let Err(e) = system_deps::Config::new().probe() {
+        eprintln!("{}", e);
         process::exit(1);
     }
-}
-
-// This is stolen from the -sys crates in gtk-rs
-fn find(package_name: &str, version: &str, shared_libs: &[&str]) -> Result<(), Error> {
-    if let Ok(inc_dir) = env::var("GTK_INCLUDE_DIR") {
-        println!("cargo:include={}", inc_dir);
-    }
-    if let Ok(lib_dir) = env::var("GTK_LIB_DIR") {
-        for lib_ in shared_libs.iter() {
-            println!("cargo:rustc-link-lib=dylib={}", lib_);
-        }
-        println!("cargo:rustc-link-search=native={}", lib_dir);
-        return Ok(());
-    }
-
-    let target = env::var("TARGET").unwrap();
-    let hardcode_shared_libs = target.contains("windows");
 
-    let mut config = Config::new();
-    config.atleast_version(version);
-    config.print_system_libs(false);
-
-    if hardcode_shared_libs {
-        config.cargo_metadata(false);
-    }
-    match config.probe(package_name) {
-        Ok(library) => {
-            if let Ok(paths) = std::env::join_paths(library.include_paths) {
-                // Exposed to other build scripts as DEP_CAIRO_INCLUDE; use env::split_paths
-                println!("cargo:include={}", paths.to_string_lossy());
-            }
-            if hardcode_shared_libs {
-                for lib_ in shared_libs.iter() {
-                    println!("cargo:rustc-link-lib=dylib={}", lib_);
-                }
-                for path in library.link_paths.iter() {
-                    println!("cargo:rustc-link-search=native={}", path.to_str().unwrap());
-                }
-            }
-            Ok(())
-        }
-        Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => {
-            for lib_ in shared_libs.iter() {
-                println!("cargo:rustc-link-lib=dylib={}", lib_);
-            }
-            Ok(())
-        }
-        Err(err) => Err(err),
-    }
-}
-
-fn check_for_pangoft2() {
-    if pkg_config::Config::new()
-        .atleast_version(PANGO_REQUIRED_VERSION)
-        .probe("pangoft2")
-        .is_ok()
-    {
-        println!("cargo:rustc-cfg=have_pangoft2");
-    }
-}
-
-fn check_for_cairo_surface_backend(backend: &str) {
-    let pkg_name = ["cairo", backend].join("-");
-    if pkg_config::Config::new()
-        .atleast_version(CAIRO_REQUIRED_VERSION)
-        .probe(&pkg_name)
-        .is_ok()
-    {
-        println!("cargo:rustc-cfg=have_cairo_{}", backend);
-    }
-}
-
-fn check_for_cairo_surface_backends() {
-    let backends = ["pdf", "ps", "svg"];
-    for name in &backends {
-        check_for_cairo_surface_backend(name);
-    }
+    generate_srgb_tables();
+    write_version();
 }
 
 /// Converts an sRGB color value to a linear sRGB color value (undoes the gamma correction).
diff --git a/src/bin/rsvg-convert.rs b/src/bin/rsvg-convert.rs
index a2a7db99..fd113c65 100644
--- a/src/bin/rsvg-convert.rs
+++ b/src/bin/rsvg-convert.rs
@@ -154,11 +154,11 @@ impl ResizeStrategy {
 
 enum Surface {
     Png(cairo::ImageSurface, OutputStream),
-    #[cfg(have_cairo_pdf)]
+    #[cfg(system_deps_have_cairo_pdf)]
     Pdf(cairo::PdfSurface, Size),
-    #[cfg(have_cairo_ps)]
+    #[cfg(system_deps_have_cairo_ps)]
     Ps(cairo::PsSurface, Size),
-    #[cfg(have_cairo_svg)]
+    #[cfg(system_deps_have_cairo_svg)]
     Svg(cairo::SvgSurface, Size),
 }
 
@@ -168,11 +168,11 @@ impl Deref for Surface {
     fn deref(&self) -> &cairo::Surface {
         match self {
             Self::Png(surface, _) => &surface,
-            #[cfg(have_cairo_pdf)]
+            #[cfg(system_deps_have_cairo_pdf)]
             Self::Pdf(surface, _) => &surface,
-            #[cfg(have_cairo_ps)]
+            #[cfg(system_deps_have_cairo_ps)]
             Self::Ps(surface, _) => &surface,
-            #[cfg(have_cairo_svg)]
+            #[cfg(system_deps_have_cairo_svg)]
             Self::Svg(surface, _) => &surface,
         }
     }
@@ -196,7 +196,7 @@ impl Surface {
         Ok(Self::Png(surface, stream))
     }
 
-    #[cfg(have_cairo_pdf)]
+    #[cfg(system_deps_have_cairo_pdf)]
     fn new_for_pdf(size: Size, stream: OutputStream) -> Result<Self, Error> {
         let surface = cairo::PdfSurface::for_stream(size.w, size.h, stream.into_write())?;
         if let Some(date) = metadata::creation_date()? {
@@ -205,31 +205,31 @@ impl Surface {
         Ok(Self::Pdf(surface, size))
     }
 
-    #[cfg(not(have_cairo_pdf))]
+    #[cfg(not(system_deps_have_cairo_pdf))]
     fn new_for_pdf(_size: Size, _stream: OutputStream) -> Result<Self, Error> {
         Err(Error("unsupported format".to_string()))
     }
 
-    #[cfg(have_cairo_ps)]
+    #[cfg(system_deps_have_cairo_ps)]
     fn new_for_ps(size: Size, stream: OutputStream, eps: bool) -> Result<Self, Error> {
         let surface = cairo::PsSurface::for_stream(size.w, size.h, stream.into_write())?;
         surface.set_eps(eps);
         Ok(Self::Ps(surface, size))
     }
 
-    #[cfg(not(have_cairo_ps))]
+    #[cfg(not(system_deps_have_cairo_ps))]
     fn new_for_ps(_size: Size, _stream: OutputStream, _eps: bool) -> Result<Self, Error> {
         Err(Error("unsupported format".to_string()))
     }
 
-    #[cfg(have_cairo_svg)]
+    #[cfg(system_deps_have_cairo_svg)]
     fn new_for_svg(size: Size, stream: OutputStream) -> Result<Self, Error> {
         let mut surface = cairo::SvgSurface::for_stream(size.w, size.h, stream.into_write())?;
         surface.set_document_unit(cairo::SvgUnit::User);
         Ok(Self::Svg(surface, size))
     }
 
-    #[cfg(not(have_cairo_svg))]
+    #[cfg(not(system_deps_have_cairo_svg))]
     fn new_for_svg(_size: Size, _stream: OutputStream) -> Result<Self, Error> {
         Err(Error("unsupported format".to_string()))
     }
@@ -530,13 +530,13 @@ impl Converter {
 fn parse_args() -> Result<Converter, Error> {
     let supported_formats = vec![
         "Png",
-        #[cfg(have_cairo_pdf)]
+        #[cfg(system_deps_have_cairo_pdf)]
         "Pdf",
-        #[cfg(have_cairo_ps)]
+        #[cfg(system_deps_have_cairo_ps)]
         "Ps",
-        #[cfg(have_cairo_ps)]
+        #[cfg(system_deps_have_cairo_ps)]
         "Eps",
-        #[cfg(have_cairo_svg)]
+        #[cfg(system_deps_have_cairo_svg)]
         "Svg",
     ];
 
diff --git a/tests/src/cmdline/rsvg_convert.rs b/tests/src/cmdline/rsvg_convert.rs
index 900c5141..bd281665 100644
--- a/tests/src/cmdline/rsvg_convert.rs
+++ b/tests/src/cmdline/rsvg_convert.rs
@@ -8,7 +8,7 @@ use crate::predicates::file;
 
 use assert_cmd::assert::IntoOutputPredicate;
 use assert_cmd::Command;
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 use chrono::{TimeZone, Utc};
 use predicates::boolean::*;
 use predicates::prelude::*;
@@ -116,7 +116,7 @@ fn output_format_png() {
         .stdout(file::is_png());
 }
 
-#[cfg(have_cairo_ps)]
+#[cfg(system_deps_have_cairo_ps)]
 #[test]
 fn output_format_ps() {
     RsvgConvert::new_with_input("tests/fixtures/dimensions/521-with-viewbox.svg")
@@ -126,7 +126,7 @@ fn output_format_ps() {
         .stdout(file::is_ps());
 }
 
-#[cfg(have_cairo_ps)]
+#[cfg(system_deps_have_cairo_ps)]
 #[test]
 fn output_format_eps() {
     RsvgConvert::new_with_input("tests/fixtures/dimensions/521-with-viewbox.svg")
@@ -136,7 +136,7 @@ fn output_format_eps() {
         .stdout(file::is_eps());
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn output_format_pdf() {
     RsvgConvert::new_with_input("tests/fixtures/dimensions/521-with-viewbox.svg")
@@ -146,7 +146,7 @@ fn output_format_pdf() {
         .stdout(file::is_pdf());
 }
 
-#[cfg(have_cairo_svg)]
+#[cfg(system_deps_have_cairo_svg)]
 #[test]
 fn output_format_svg_short_option() {
     RsvgConvert::new_with_input("tests/fixtures/dimensions/521-with-viewbox.svg")
@@ -247,7 +247,7 @@ fn multiple_input_files_not_allowed_for_png_output() {
         ));
 }
 
-#[cfg(have_cairo_ps)]
+#[cfg(system_deps_have_cairo_ps)]
 #[test]
 fn multiple_input_files_accepted_for_eps_output() {
     let one = Path::new("tests/fixtures/dimensions/521-with-viewbox.svg");
@@ -261,7 +261,7 @@ fn multiple_input_files_accepted_for_eps_output() {
         .stdout(file::is_eps());
 }
 
-#[cfg(have_cairo_ps)]
+#[cfg(system_deps_have_cairo_ps)]
 #[test]
 fn multiple_input_files_accepted_for_ps_output() {
     let one = Path::new("tests/fixtures/dimensions/521-with-viewbox.svg");
@@ -275,7 +275,7 @@ fn multiple_input_files_accepted_for_ps_output() {
         .stdout(file::is_ps());
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn multiple_input_files_create_multi_page_pdf_output() {
     let one = Path::new("tests/fixtures/dimensions/521-with-viewbox.svg");
@@ -291,7 +291,7 @@ fn multiple_input_files_create_multi_page_pdf_output() {
         .stdout(file::is_pdf().with_page_count(3));
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn env_source_data_epoch_controls_pdf_creation_date() {
     let input = Path::new("tests/fixtures/dimensions/521-with-viewbox.svg");
@@ -305,7 +305,7 @@ fn env_source_data_epoch_controls_pdf_creation_date() {
         .stdout(file::is_pdf().with_creation_date(Utc.timestamp(date, 0)));
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn env_source_data_epoch_no_digits() {
     // intentionally not testing for the full error string here
@@ -319,7 +319,7 @@ fn env_source_data_epoch_no_digits() {
         .stderr(starts_with("Environment variable $SOURCE_DATE_EPOCH"));
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn env_source_data_epoch_trailing_garbage() {
     // intentionally not testing for the full error string here
@@ -333,7 +333,7 @@ fn env_source_data_epoch_trailing_garbage() {
         .stderr(starts_with("Environment variable $SOURCE_DATE_EPOCH"));
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn env_source_data_epoch_empty() {
     // intentionally not testing for the full error string here
@@ -531,7 +531,7 @@ fn negative_resolution_is_invalid() {
         .stderr(contains("Invalid resolution"));
 }
 
-#[cfg(have_cairo_pdf)]
+#[cfg(system_deps_have_cairo_pdf)]
 #[test]
 fn pdf_page_size() {
     RsvgConvert::new_with_input("tests/fixtures/dimensions/521-with-viewbox.svg")
diff --git a/tests/src/utils.rs b/tests/src/utils.rs
index 2e500ff6..4795055f 100644
--- a/tests/src/utils.rs
+++ b/tests/src/utils.rs
@@ -46,7 +46,7 @@ pub fn render_document<F: FnOnce(&cairo::Context)>(
     res.and_then(|_| Ok(SharedImageSurface::wrap(output, SurfaceType::SRgb)?))
 }
 
-#[cfg(have_pangoft2)]
+#[cfg(system_deps_have_pangoft2)]
 mod pango_ft2 {
     use super::*;
     use fontconfig_sys::fontconfig;
@@ -91,14 +91,14 @@ mod pango_ft2 {
     }
 }
 
-#[cfg(have_pangoft2)]
+#[cfg(system_deps_have_pangoft2)]
 pub fn setup_font_map() {
     unsafe {
         self::pango_ft2::load_test_fonts();
     }
 }
 
-#[cfg(not(have_pangoft2))]
+#[cfg(not(system_deps_have_pangoft2))]
 pub fn setup_font_map() {}
 
 pub fn setup_language() {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]