blob: 717c87ad3050fc283e4cf20954948d2208d54a8d [file] [log] [blame]
Zach Reizner20d71f82018-05-03 13:19:37 -07001// Copyright 2018 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Zach Reizner20d71f82018-05-03 13:19:37 -07005use std::env;
6use std::ffi::OsStr;
7use std::fs;
8use std::path::{Path, PathBuf};
9use std::process::Command;
10
11// Performs a recursive search for a file with name under path and returns the full path if such a
12// file is found.
13fn scan_path<P: AsRef<Path>, O: AsRef<OsStr>>(path: P, name: O) -> Option<PathBuf> {
Daniel Verkamp35712b22021-08-19 17:13:55 -070014 for entry in (fs::read_dir(path).ok()?).flatten() {
15 let file_type = match entry.file_type() {
16 Ok(t) => t,
17 Err(_) => continue,
18 };
Zach Reizner20d71f82018-05-03 13:19:37 -070019
Daniel Verkamp35712b22021-08-19 17:13:55 -070020 if file_type.is_file() && entry.file_name() == name.as_ref() {
21 return Some(entry.path());
22 } else if file_type.is_dir() {
23 if let Some(found) = scan_path(entry.path(), name.as_ref()) {
24 return Some(found);
Zach Reizner20d71f82018-05-03 13:19:37 -070025 }
26 }
27 }
28 None
29}
30
31// Searches for the given protocol in both the system wide and bundles protocols path.
32fn find_protocol(name: &str) -> PathBuf {
Robert Tarasov3cfec9e2021-02-01 16:33:40 -080033 let protocols_path = pkg_config::get_variable("wayland-protocols", "pkgdatadir")
Andrew Walbran9cfdbd92021-01-11 17:40:34 +000034 .unwrap_or_else(|_| "/usr/share/wayland-protocols".to_owned());
Zach Reizner20d71f82018-05-03 13:19:37 -070035 let protocol_file_name = PathBuf::from(format!("{}.xml", name));
36
37 // Prioritize the systems wayland protocols before using the bundled ones.
38 if let Some(found) = scan_path(protocols_path, &protocol_file_name) {
39 return found;
40 }
41
42 // Use bundled protocols as a fallback.
43 let protocol_path = Path::new("protocol").join(protocol_file_name);
Zach Reizner55a9e502018-10-03 10:22:32 -070044 assert!(
45 protocol_path.is_file(),
46 "unable to locate wayland protocol specification for `{}`",
47 name
48 );
Zach Reizner20d71f82018-05-03 13:19:37 -070049 protocol_path
50}
51
52fn compile_protocol<P: AsRef<Path>>(name: &str, out: P) -> PathBuf {
53 let in_protocol = find_protocol(name);
54 println!("cargo:rerun-if-changed={}", in_protocol.display());
55 let out_code = out.as_ref().join(format!("{}.c", name));
56 let out_header = out.as_ref().join(format!("{}.h", name));
57 eprintln!("building protocol: {}", name);
58 Command::new("wayland-scanner")
59 .arg("code")
60 .arg(&in_protocol)
61 .arg(&out_code)
62 .output()
Zach Reiznerd09392e2021-03-12 12:03:48 -080063 .expect("wayland-scanner code failed");
Zach Reizner20d71f82018-05-03 13:19:37 -070064 Command::new("wayland-scanner")
65 .arg("client-header")
66 .arg(&in_protocol)
67 .arg(&out_header)
68 .output()
Zach Reiznerd09392e2021-03-12 12:03:48 -080069 .expect("wayland-scanner client-header failed");
Zach Reizner20d71f82018-05-03 13:19:37 -070070 out_code
71}
72
73fn main() {
74 println!("cargo:rerun-if-env-changed=WAYLAND_PROTOCOLS_PATH");
75 let out_dir = env::var("OUT_DIR").unwrap();
76
77 let mut build = cc::Build::new();
78 build.warnings(true);
79 build.warnings_into_errors(true);
80 build.include(&out_dir);
81 build.flag("-std=gnu11");
82 build.file("src/display_wl.c");
83 println!("cargo:rerun-if-changed=src/display_wl.c");
84
Zach Reizner55a9e502018-10-03 10:22:32 -070085 for protocol in &[
86 "aura-shell",
87 "linux-dmabuf-unstable-v1",
Robert Tarasov3cfec9e2021-02-01 16:33:40 -080088 "xdg-shell",
Zach Reizner55a9e502018-10-03 10:22:32 -070089 "viewporter",
Jason Macnak114d7d72021-05-21 09:33:27 -070090 "virtio-gpu-metadata-v1",
Zach Reizner55a9e502018-10-03 10:22:32 -070091 ] {
Zach Reizner20d71f82018-05-03 13:19:37 -070092 build.file(compile_protocol(protocol, &out_dir));
93 }
94 build.compile("display_wl");
95
96 println!("cargo:rustc-link-lib=dylib=wayland-client");
97}