1 // Copyright 2025 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 libaom.
16
17 use std::env;
18 use std::path::Path;
19 use std::path::PathBuf;
20
21 extern crate pkg_config;
22
main()23 fn main() {
24 println!("cargo:rerun-if-changed=build.rs");
25
26 let build_target = std::env::var("TARGET").unwrap();
27 let build_dir = if build_target.contains("android") {
28 if build_target.contains("x86_64") {
29 "build.android/x86_64"
30 } else if build_target.contains("x86") {
31 "build.android/x86"
32 } else if build_target.contains("aarch64") {
33 "build.android/aarch64"
34 } else if build_target.contains("arm") {
35 "build.android/arm"
36 } else {
37 panic!("Unknown target_arch for android. Must be one of x86, x86_64, arm, aarch64.");
38 }
39 } else {
40 "build.libavif"
41 };
42
43 let project_root = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
44 // Prefer locally built libaom if available.
45 let abs_library_dir = PathBuf::from(&project_root).join("aom");
46 let abs_object_dir = PathBuf::from(&abs_library_dir).join(build_dir);
47 let library_file = PathBuf::from(&abs_object_dir).join("libaom.a");
48 let mut include_paths: Vec<String> = Vec::new();
49 if Path::new(&library_file).exists() {
50 println!("cargo:rustc-link-search={}", abs_object_dir.display());
51 println!("cargo:rustc-link-lib=static=aom");
52 let version_dir = PathBuf::from(&abs_library_dir)
53 .join(build_dir)
54 .join("config");
55 include_paths.push(format!("-I{}", version_dir.display()));
56 let include_dir = PathBuf::from(&abs_library_dir);
57 include_paths.push(format!("-I{}", include_dir.display()));
58 } else {
59 let library = pkg_config::Config::new().probe("aom");
60 if library.is_err() {
61 println!(
62 "aom could not be found with pkg-config. Install the system library or run aom.cmd"
63 );
64 }
65 let library = library.unwrap();
66 for lib in &library.libs {
67 println!("cargo:rustc-link-lib={lib}");
68 }
69 for link_path in &library.link_paths {
70 println!("cargo:rustc-link-search={}", link_path.display());
71 }
72 for include_path in &library.include_paths {
73 include_paths.push(format!("-I{}", include_path.display()));
74 }
75 }
76
77 // Generate bindings.
78 let header_file = PathBuf::from(&project_root).join("wrapper.h");
79 let outfile = PathBuf::from(&project_root).join("aom.rs");
80 let bindings = bindgen::Builder::default()
81 .header(header_file.into_os_string().into_string().unwrap())
82 .clang_args(&include_paths)
83 .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
84 .layout_tests(false)
85 .generate_comments(false);
86 // TODO: b/402941742 - Add an allowlist to only generate bindings for necessary items.
87 let bindings = bindings
88 .generate()
89 .unwrap_or_else(|_| panic!("Unable to generate bindings for aom."));
90 bindings
91 .write_to_file(outfile.as_path())
92 .unwrap_or_else(|_| panic!("Couldn't write bindings for aom"));
93 println!(
94 "cargo:rustc-env=CRABBYAVIF_AOM_BINDINGS_RS={}",
95 outfile.display()
96 );
97 }
98