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/arm64-v8a"
37 } else if build_target.contains("arm") {
38 "build.android/armeabi-v7a"
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("libyuv");
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 "yuv.lib"
51 } else {
52 "libyuv.a"
53 });
54 let extra_includes_str;
55 if Path::new(&library_file).exists() {
56 println!("cargo:rustc-link-lib=static=yuv");
57 println!("cargo:rustc-link-search={}", abs_object_dir.display());
58 let version_dir = PathBuf::from(&abs_library_dir).join(path_buf(&["include"]));
59 extra_includes_str = format!("-I{}", version_dir.display());
60 } else {
61 // Local library was not found. Look for a system library.
62 match pkg_config::Config::new().probe("yuv") {
63 Ok(library) => {
64 for lib in &library.libs {
65 println!("cargo:rustc-link-lib={lib}");
66 }
67 for link_path in &library.link_paths {
68 println!("cargo:rustc-link-search={}", link_path.display());
69 }
70 let mut include_str = String::new();
71 for include_path in &library.include_paths {
72 include_str.push_str("-I");
73 include_str.push_str(include_path.to_str().unwrap());
74 }
75 extra_includes_str = include_str;
76 }
77 Err(_) => {
78 // Try to build without any extra flags.
79 println!("cargo:rustc-link-lib=yuv");
80 extra_includes_str = String::new();
81 }
82 }
83 }
84
85 // Generate bindings.
86 let header_file = PathBuf::from(&project_root).join("wrapper.h");
87 let outdir = std::env::var("OUT_DIR").expect("OUT_DIR not set");
88 let outfile = PathBuf::from(&outdir).join("libyuv_bindgen.rs");
89 let mut bindings = bindgen::Builder::default()
90 .header(header_file.into_os_string().into_string().unwrap())
91 .clang_arg(extra_includes_str)
92 .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
93 .layout_tests(false)
94 .generate_comments(false);
95 let allowlist_items = &[
96 "YuvConstants",
97 "FilterMode",
98 "ARGBAttenuate",
99 "ARGBToABGR",
100 "ARGBUnattenuate",
101 "Convert16To8Plane",
102 "HalfFloatPlane",
103 "ScalePlane_12",
104 "ScalePlane",
105 "FilterMode_kFilterBilinear",
106 "FilterMode_kFilterBox",
107 "FilterMode_kFilterNone",
108 "I010AlphaToARGBMatrixFilter",
109 "I010AlphaToARGBMatrix",
110 "I010ToARGBMatrixFilter",
111 "I010ToARGBMatrix",
112 "I012ToARGBMatrix",
113 "I210AlphaToARGBMatrixFilter",
114 "I210AlphaToARGBMatrix",
115 "I210ToARGBMatrixFilter",
116 "I210ToARGBMatrix",
117 "I400ToARGBMatrix",
118 "I410AlphaToARGBMatrix",
119 "I410ToARGBMatrix",
120 "I420AlphaToARGBMatrixFilter",
121 "I420AlphaToARGBMatrix",
122 "I420ToARGBMatrixFilter",
123 "I420ToARGBMatrix",
124 "I420ToRGB24MatrixFilter",
125 "I420ToRGB24Matrix",
126 "I420ToRGB565Matrix",
127 "I420ToRGBAMatrix",
128 "I422AlphaToARGBMatrixFilter",
129 "I422AlphaToARGBMatrix",
130 "I422ToARGBMatrixFilter",
131 "I422ToARGBMatrix",
132 "I422ToRGB24MatrixFilter",
133 "I422ToRGB565Matrix",
134 "I422ToRGBAMatrix",
135 "I444AlphaToARGBMatrix",
136 "I444ToARGBMatrix",
137 "I444ToRGB24Matrix",
138 "NV12ToARGBMatrix",
139 "NV21ToARGBMatrix",
140 "P010ToAR30Matrix",
141 "P010ToARGBMatrix",
142 "AR30ToAB30",
143 "kYuv2020Constants",
144 "kYuvF709Constants",
145 "kYuvH709Constants",
146 "kYuvI601Constants",
147 "kYuvJPEGConstants",
148 "kYuvV2020Constants",
149 "kYvu2020Constants",
150 "kYvuF709Constants",
151 "kYvuH709Constants",
152 "kYvuI601Constants",
153 "kYvuJPEGConstants",
154 "kYvuV2020Constants",
155 ];
156 for allowlist_item in allowlist_items {
157 bindings = bindings.allowlist_item(allowlist_item);
158 }
159 let bindings = bindings
160 .generate()
161 .unwrap_or_else(|_| panic!("Unable to generate bindings for libyuv."));
162 bindings
163 .write_to_file(outfile.as_path())
164 .unwrap_or_else(|_| panic!("Couldn't write bindings for libyuv"));
165 }
166