xref: /aosp_15_r20/external/crosvm/gpu_display/build.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2018 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::env;
6*bb4ee6a4SAndroid Build Coastguard Worker use std::ffi::OsStr;
7*bb4ee6a4SAndroid Build Coastguard Worker use std::fs;
8*bb4ee6a4SAndroid Build Coastguard Worker use std::path::Path;
9*bb4ee6a4SAndroid Build Coastguard Worker use std::path::PathBuf;
10*bb4ee6a4SAndroid Build Coastguard Worker use std::process::Command;
11*bb4ee6a4SAndroid Build Coastguard Worker 
12*bb4ee6a4SAndroid Build Coastguard Worker // Performs a recursive search for a file with name under path and returns the full path if such a
13*bb4ee6a4SAndroid Build Coastguard Worker // file is found.
scan_path<P: AsRef<Path>, O: AsRef<OsStr>>(path: P, name: O) -> Option<PathBuf>14*bb4ee6a4SAndroid Build Coastguard Worker fn scan_path<P: AsRef<Path>, O: AsRef<OsStr>>(path: P, name: O) -> Option<PathBuf> {
15*bb4ee6a4SAndroid Build Coastguard Worker     for entry in (fs::read_dir(path).ok()?).flatten() {
16*bb4ee6a4SAndroid Build Coastguard Worker         let file_type = match entry.file_type() {
17*bb4ee6a4SAndroid Build Coastguard Worker             Ok(t) => t,
18*bb4ee6a4SAndroid Build Coastguard Worker             Err(_) => continue,
19*bb4ee6a4SAndroid Build Coastguard Worker         };
20*bb4ee6a4SAndroid Build Coastguard Worker 
21*bb4ee6a4SAndroid Build Coastguard Worker         if file_type.is_file() && entry.file_name() == name.as_ref() {
22*bb4ee6a4SAndroid Build Coastguard Worker             return Some(entry.path());
23*bb4ee6a4SAndroid Build Coastguard Worker         } else if file_type.is_dir() {
24*bb4ee6a4SAndroid Build Coastguard Worker             if let Some(found) = scan_path(entry.path(), name.as_ref()) {
25*bb4ee6a4SAndroid Build Coastguard Worker                 return Some(found);
26*bb4ee6a4SAndroid Build Coastguard Worker             }
27*bb4ee6a4SAndroid Build Coastguard Worker         }
28*bb4ee6a4SAndroid Build Coastguard Worker     }
29*bb4ee6a4SAndroid Build Coastguard Worker     None
30*bb4ee6a4SAndroid Build Coastguard Worker }
31*bb4ee6a4SAndroid Build Coastguard Worker 
32*bb4ee6a4SAndroid Build Coastguard Worker // Searches for the given protocol in both the system wide and bundles protocols path.
find_protocol(name: &str) -> PathBuf33*bb4ee6a4SAndroid Build Coastguard Worker fn find_protocol(name: &str) -> PathBuf {
34*bb4ee6a4SAndroid Build Coastguard Worker     let protocol_file_name = PathBuf::from(format!("{}.xml", name));
35*bb4ee6a4SAndroid Build Coastguard Worker     // Prioritize the systems wayland protocols before using the bundled ones.
36*bb4ee6a4SAndroid Build Coastguard Worker     if let Ok(protocols_path) = pkg_config::get_variable("wayland-protocols", "pkgdatadir") {
37*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
38*bb4ee6a4SAndroid Build Coastguard Worker             return found;
39*bb4ee6a4SAndroid Build Coastguard Worker         }
40*bb4ee6a4SAndroid Build Coastguard Worker     }
41*bb4ee6a4SAndroid Build Coastguard Worker     let protocols_path = format!("/usr/share/wayland-protocols/stable/{}", name);
42*bb4ee6a4SAndroid Build Coastguard Worker     if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
43*bb4ee6a4SAndroid Build Coastguard Worker         return found;
44*bb4ee6a4SAndroid Build Coastguard Worker     }
45*bb4ee6a4SAndroid Build Coastguard Worker     // Use bundled protocols as a fallback.
46*bb4ee6a4SAndroid Build Coastguard Worker     let protocol_path = Path::new("protocol").join(protocol_file_name);
47*bb4ee6a4SAndroid Build Coastguard Worker     assert!(
48*bb4ee6a4SAndroid Build Coastguard Worker         protocol_path.is_file(),
49*bb4ee6a4SAndroid Build Coastguard Worker         "unable to locate wayland protocol specification for `{}`",
50*bb4ee6a4SAndroid Build Coastguard Worker         name
51*bb4ee6a4SAndroid Build Coastguard Worker     );
52*bb4ee6a4SAndroid Build Coastguard Worker     protocol_path
53*bb4ee6a4SAndroid Build Coastguard Worker }
54*bb4ee6a4SAndroid Build Coastguard Worker 
compile_protocol<P: AsRef<Path>>(name: &str, out: P) -> PathBuf55*bb4ee6a4SAndroid Build Coastguard Worker fn compile_protocol<P: AsRef<Path>>(name: &str, out: P) -> PathBuf {
56*bb4ee6a4SAndroid Build Coastguard Worker     let in_protocol = find_protocol(name);
57*bb4ee6a4SAndroid Build Coastguard Worker     println!("cargo:rerun-if-changed={}", in_protocol.display());
58*bb4ee6a4SAndroid Build Coastguard Worker     let out_code = out.as_ref().join(format!("{}.c", name));
59*bb4ee6a4SAndroid Build Coastguard Worker     let out_header = out.as_ref().join(format!("{}.h", name));
60*bb4ee6a4SAndroid Build Coastguard Worker     eprintln!("building protocol: {}", name);
61*bb4ee6a4SAndroid Build Coastguard Worker 
62*bb4ee6a4SAndroid Build Coastguard Worker     let wayland_scanner = which::which("wayland-scanner")
63*bb4ee6a4SAndroid Build Coastguard Worker         .expect("missing wayland-scanner - please install libwayland-dev");
64*bb4ee6a4SAndroid Build Coastguard Worker 
65*bb4ee6a4SAndroid Build Coastguard Worker     Command::new(&wayland_scanner)
66*bb4ee6a4SAndroid Build Coastguard Worker         .arg("code")
67*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&in_protocol)
68*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&out_code)
69*bb4ee6a4SAndroid Build Coastguard Worker         .output()
70*bb4ee6a4SAndroid Build Coastguard Worker         .expect("wayland-scanner code failed");
71*bb4ee6a4SAndroid Build Coastguard Worker     Command::new(&wayland_scanner)
72*bb4ee6a4SAndroid Build Coastguard Worker         .arg("client-header")
73*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&in_protocol)
74*bb4ee6a4SAndroid Build Coastguard Worker         .arg(&out_header)
75*bb4ee6a4SAndroid Build Coastguard Worker         .output()
76*bb4ee6a4SAndroid Build Coastguard Worker         .expect("wayland-scanner client-header failed");
77*bb4ee6a4SAndroid Build Coastguard Worker     out_code
78*bb4ee6a4SAndroid Build Coastguard Worker }
79*bb4ee6a4SAndroid Build Coastguard Worker 
build_wayland()80*bb4ee6a4SAndroid Build Coastguard Worker fn build_wayland() {
81*bb4ee6a4SAndroid Build Coastguard Worker     println!("cargo:rerun-if-env-changed=WAYLAND_PROTOCOLS_PATH");
82*bb4ee6a4SAndroid Build Coastguard Worker     let out_dir = env::var("OUT_DIR").unwrap();
83*bb4ee6a4SAndroid Build Coastguard Worker 
84*bb4ee6a4SAndroid Build Coastguard Worker     let mut build = cc::Build::new();
85*bb4ee6a4SAndroid Build Coastguard Worker     build.warnings(true);
86*bb4ee6a4SAndroid Build Coastguard Worker     build.warnings_into_errors(true);
87*bb4ee6a4SAndroid Build Coastguard Worker     build.include(&out_dir);
88*bb4ee6a4SAndroid Build Coastguard Worker     build.flag("-std=gnu11");
89*bb4ee6a4SAndroid Build Coastguard Worker     build.file("src/display_wl.c");
90*bb4ee6a4SAndroid Build Coastguard Worker     println!("cargo:rerun-if-changed=src/display_wl.c");
91*bb4ee6a4SAndroid Build Coastguard Worker 
92*bb4ee6a4SAndroid Build Coastguard Worker     for protocol in &[
93*bb4ee6a4SAndroid Build Coastguard Worker         "aura-shell",
94*bb4ee6a4SAndroid Build Coastguard Worker         "linux-dmabuf-unstable-v1",
95*bb4ee6a4SAndroid Build Coastguard Worker         "xdg-shell",
96*bb4ee6a4SAndroid Build Coastguard Worker         "viewporter",
97*bb4ee6a4SAndroid Build Coastguard Worker         "virtio-gpu-metadata-v1",
98*bb4ee6a4SAndroid Build Coastguard Worker     ] {
99*bb4ee6a4SAndroid Build Coastguard Worker         build.file(compile_protocol(protocol, &out_dir));
100*bb4ee6a4SAndroid Build Coastguard Worker     }
101*bb4ee6a4SAndroid Build Coastguard Worker     build.compile("display_wl");
102*bb4ee6a4SAndroid Build Coastguard Worker 
103*bb4ee6a4SAndroid Build Coastguard Worker     println!("cargo:rustc-link-lib=dylib=wayland-client");
104*bb4ee6a4SAndroid Build Coastguard Worker }
105*bb4ee6a4SAndroid Build Coastguard Worker 
main()106*bb4ee6a4SAndroid Build Coastguard Worker fn main() {
107*bb4ee6a4SAndroid Build Coastguard Worker     // Skip installing dependencies when generating documents.
108*bb4ee6a4SAndroid Build Coastguard Worker     if std::env::var("CARGO_DOC").is_ok() {
109*bb4ee6a4SAndroid Build Coastguard Worker         return;
110*bb4ee6a4SAndroid Build Coastguard Worker     }
111*bb4ee6a4SAndroid Build Coastguard Worker 
112*bb4ee6a4SAndroid Build Coastguard Worker     match std::env::var("CARGO_CFG_TARGET_OS").as_deref().unwrap() {
113*bb4ee6a4SAndroid Build Coastguard Worker         "linux" | "android" => {
114*bb4ee6a4SAndroid Build Coastguard Worker             build_wayland();
115*bb4ee6a4SAndroid Build Coastguard Worker         }
116*bb4ee6a4SAndroid Build Coastguard Worker         _ => {}
117*bb4ee6a4SAndroid Build Coastguard Worker     }
118*bb4ee6a4SAndroid Build Coastguard Worker }
119