1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Build rust library and bindings for libyuv.
16 
17 use std::env;
18 use std::path::Path;
19 use std::path::PathBuf;
20 
path_buf(inputs: &[&str]) -> PathBuf21 fn path_buf(inputs: &[&str]) -> PathBuf {
22     let path: PathBuf = inputs.iter().collect();
23     path
24 }
25 
main()26 fn main() {
27     println!("cargo:rerun-if-changed=build.rs");
28 
29     let build_target = std::env::var("TARGET").unwrap();
30     let build_dir = if build_target.contains("android") {
31         if build_target.contains("x86_64") {
32             "build.android/x86_64"
33         } else if build_target.contains("x86") {
34             "build.android/x86"
35         } else if build_target.contains("aarch64") {
36             "build.android/aarch64"
37         } else if build_target.contains("arm") {
38             "build.android/arm"
39         } else {
40             panic!("Unknown target_arch for android. Must be one of x86, x86_64, arm, aarch64.");
41         }
42     } else {
43         "build"
44     };
45 
46     let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
47     let abs_library_dir = PathBuf::from(&project_root).join("libgav1");
48     let abs_object_dir = PathBuf::from(&abs_library_dir).join(build_dir);
49     let library_file = PathBuf::from(&abs_object_dir).join(if cfg!(target_os = "windows") {
50         "libgav1.lib"
51     } else {
52         "libgav1.a"
53     });
54     if !Path::new(&library_file).exists() {
55         panic!("libgav1 not found. Run libgav1.cmd.");
56     }
57     println!("cargo:rustc-link-search={}", abs_object_dir.display());
58     let library_name = if cfg!(target_os = "windows") { "libgav1" } else { "gav1" };
59     println!("cargo:rustc-link-lib=static={library_name}");
60 
61     // Generate bindings.
62     let header_file = PathBuf::from(&abs_library_dir).join(path_buf(&["src", "gav1", "decoder.h"]));
63     let version_dir = PathBuf::from(&abs_library_dir).join(path_buf(&["src"]));
64     let outdir = std::env::var("OUT_DIR").expect("OUT_DIR not set");
65     let outfile = PathBuf::from(&outdir).join("libgav1_bindgen.rs");
66     let extra_includes_str = format!("-I{}", version_dir.display());
67     let mut bindings = bindgen::Builder::default()
68         .header(header_file.into_os_string().into_string().unwrap())
69         .clang_arg(extra_includes_str)
70         .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
71         .layout_tests(false)
72         .generate_comments(false);
73     let allowlist_items = &[
74         "Libgav1DecoderCreate",
75         "Libgav1DecoderDequeueFrame",
76         "Libgav1DecoderDestroy",
77         "Libgav1DecoderEnqueueFrame",
78         "Libgav1DecoderSettingsInitDefault",
79     ];
80     for allowlist_item in allowlist_items {
81         bindings = bindings.allowlist_item(allowlist_item);
82     }
83     let bindings = bindings
84         .generate()
85         .unwrap_or_else(|_| panic!("Unable to generate bindings for libgav1."));
86     bindings
87         .write_to_file(outfile.as_path())
88         .unwrap_or_else(|_| panic!("Couldn't write bindings for libgav1"));
89 }
90