1 #[cfg(feature = "bindgen")]
2 extern crate bindgen;
3 
4 #[cfg(feature = "pkg-config")]
5 extern crate pkg_config;
6 
7 extern crate cc;
8 extern crate glob;
9 extern crate itertools;
10 
11 use std::path::PathBuf;
12 use std::{env, fs};
13 
14 use itertools::Itertools;
15 
16 #[cfg(feature = "bindgen")]
generate_bindings(defs: Vec<&str>, headerpaths: Vec<PathBuf>)17 fn generate_bindings(defs: Vec<&str>, headerpaths: Vec<PathBuf>) {
18     let bindings = bindgen::Builder::default()
19         .header("zstd.h")
20         .blacklist_type("max_align_t")
21         .size_t_is_usize(true)
22         .use_core()
23         .rustified_enum(".*")
24         .clang_args(
25             headerpaths
26                 .into_iter()
27                 .map(|path| format!("-I{}", path.display())),
28         )
29         .clang_args(defs.into_iter().map(|def| format!("-D{}", def)));
30 
31     #[cfg(feature = "experimental")]
32     let bindings = bindings
33         .clang_arg("-DZSTD_STATIC_LINKING_ONLY")
34         .clang_arg("-DZDICT_STATIC_LINKING_ONLY");
35 
36     #[cfg(not(feature = "std"))]
37     let bindings = bindings.ctypes_prefix("libc");
38 
39     let bindings = bindings.generate().expect("Unable to generate bindings");
40 
41     let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
42     bindings
43         .write_to_file(out_path.join("bindings.rs"))
44         .expect("Could not write bindings");
45 }
46 
47 #[cfg(not(feature = "bindgen"))]
generate_bindings(_: Vec<&str>, _: Vec<PathBuf>)48 fn generate_bindings(_: Vec<&str>, _: Vec<PathBuf>) {}
49 
50 #[cfg(feature = "pkg-config")]
pkg_config() -> (Vec<&'static str>, Vec<PathBuf>)51 fn pkg_config() -> (Vec<&'static str>, Vec<PathBuf>) {
52     let library = pkg_config::Config::new()
53         .statik(true)
54         .cargo_metadata(!cfg!(feature = "non-cargo"))
55         .probe("libzstd")
56         .expect("Can't probe for zstd in pkg-config");
57     (vec!["PKG_CONFIG"], library.include_paths)
58 }
59 
60 #[cfg(not(feature = "pkg-config"))]
pkg_config() -> (Vec<&'static str>, Vec<PathBuf>)61 fn pkg_config() -> (Vec<&'static str>, Vec<PathBuf>) {
62     unimplemented!()
63 }
64 
65 #[cfg(not(feature = "legacy"))]
set_legacy(_config: &mut cc::Build)66 fn set_legacy(_config: &mut cc::Build) {}
67 
68 #[cfg(feature = "legacy")]
set_legacy(config: &mut cc::Build)69 fn set_legacy(config: &mut cc::Build) {
70     config.define("ZSTD_LEGACY_SUPPORT", Some("1"));
71 }
72 
73 #[cfg(feature = "zstdmt")]
set_pthread(config: &mut cc::Build)74 fn set_pthread(config: &mut cc::Build) {
75     config.flag("-pthread");
76 }
77 
78 #[cfg(not(feature = "zstdmt"))]
set_pthread(_config: &mut cc::Build)79 fn set_pthread(_config: &mut cc::Build) {}
80 
81 #[cfg(feature = "zstdmt")]
enable_threading(config: &mut cc::Build)82 fn enable_threading(config: &mut cc::Build) {
83     config.define("ZSTD_MULTITHREAD", Some(""));
84 }
85 
86 #[cfg(not(feature = "zstdmt"))]
enable_threading(_config: &mut cc::Build)87 fn enable_threading(_config: &mut cc::Build) {}
88 
compile_zstd()89 fn compile_zstd() {
90     let mut config = cc::Build::new();
91 
92     let globs = &[
93         "zstd/lib/common/*.c",
94         "zstd/lib/compress/*.c",
95         "zstd/lib/decompress/*.c",
96         "zstd/lib/legacy/*.c",
97         "zstd/lib/dictBuilder/*.c",
98     ];
99 
100     for pattern in globs {
101         for path in glob::glob(pattern).unwrap() {
102             let path = path.unwrap();
103             config.file(path);
104         }
105     }
106 
107     // Some extra parameters
108     config.opt_level(3);
109     config.include("zstd/lib/");
110     config.include("zstd/lib/common");
111     config.include("zstd/lib/legacy");
112     config.warnings(false);
113 
114     config.define("ZSTD_LIB_DEPRECATED", Some("0"));
115 
116     // Hide symbols from resulting library,
117     // so we can be used with another zstd-linking lib.
118     // See https://github.com/gyscos/zstd-rs/issues/58
119     config.flag("-fvisibility=hidden");
120     config.define("ZSTDLIB_VISIBILITY", Some(""));
121     config.define("ZDICTLIB_VISIBILITY", Some(""));
122     config.define("ZSTDERRORLIB_VISIBILITY", Some(""));
123 
124     set_pthread(&mut config);
125     set_legacy(&mut config);
126     enable_threading(&mut config);
127 
128     // Compile!
129     config.compile("libzstd.a");
130 
131     let src = env::current_dir().unwrap().join("zstd").join("lib");
132     let dst = PathBuf::from(env::var_os("OUT_DIR").unwrap());
133     let include = dst.join("include");
134     fs::create_dir_all(&include).unwrap();
135     fs::copy(src.join("zstd.h"), include.join("zstd.h")).unwrap();
136     fs::copy(
137         src.join("common").join("zstd_errors.h"),
138         include.join("zstd_errors.h"),
139     )
140     .unwrap();
141     fs::copy(
142         src.join("dictBuilder").join("zdict.h"),
143         include.join("zdict.h"),
144     )
145     .unwrap();
146     println!("cargo:root={}", dst.display());
147 }
148 
main()149 fn main() {
150     let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default();
151     let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
152 
153     if target_arch == "wasm32" || target_os == "hermit" {
154         println!("cargo:rustc-cfg=feature=\"std\"");
155     }
156 
157     // println!("cargo:rustc-link-lib=zstd");
158     let (defs, headerpaths) = if cfg!(feature = "pkg-config") {
159         pkg_config()
160     } else {
161         if !PathBuf::from("zstd/lib").exists() {
162             panic!("Folder 'zstd/lib' does not exists. Maybe you forget clone 'zstd' submodule?");
163         }
164 
165         let manifest_dir = PathBuf::from(
166             env::var("CARGO_MANIFEST_DIR")
167                 .expect("Manifest dir is always set by cargo"),
168         );
169 
170         compile_zstd();
171         (vec![], vec![manifest_dir.join("zstd/lib")])
172     };
173 
174     println!("cargo:include={}", headerpaths.iter().map(|p| p.display().to_string()).join(";"));
175 
176     generate_bindings(defs, headerpaths);
177 }
178