• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2024 The Android Open Source Project
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 use cfg_expr::{
16     targets::{Arch, Family, Os},
17     Predicate, TargetPredicate,
18 };
19 use crates_index::Dependency;
20 
21 /// Parse cfg expressions in dependencies and determine if they refer to a target relevant to Android.
22 /// Dependencies are relevant if they are for Unix, Android, or Linux, and for an architecture we care about (Arm, RISC-V, or X86)
23 pub trait AndroidTarget {
24     /// Returns true if this dependency is likely to be relevant to Android.
is_android_target(&self) -> bool25     fn is_android_target(&self) -> bool;
26 }
27 
28 impl AndroidTarget for Dependency {
is_android_target(&self) -> bool29     fn is_android_target(&self) -> bool {
30         self.target().map_or(true, is_android)
31     }
32 }
33 
is_android(target: &str) -> bool34 fn is_android(target: &str) -> bool {
35     let expr = cfg_expr::Expression::parse(target);
36     if expr.is_err() {
37         return false;
38     }
39     let expr = expr.unwrap();
40     expr.eval(|pred| match pred {
41         Predicate::Target(target_predicate) => match target_predicate {
42             TargetPredicate::Family(family) => *family == Family::unix,
43             TargetPredicate::Os(os) => *os == Os::android || *os == Os::linux,
44             TargetPredicate::Arch(arch) => {
45                 [Arch::arm, Arch::aarch64, Arch::riscv32, Arch::riscv64, Arch::x86, Arch::x86_64]
46                     .contains(arch)
47             }
48             _ => true,
49         },
50         _ => true,
51     })
52 }
53 
54 #[cfg(test)]
55 mod tests {
56     use super::*;
57     #[test]
test_android_cfgs()58     fn test_android_cfgs() {
59         assert!(!is_android("asmjs-unknown-emscripten"), "Parse error");
60         assert!(!is_android("cfg(windows)"));
61         assert!(is_android("cfg(unix)"));
62         assert!(!is_android(r#"cfg(target_os = "redox")"#));
63         assert!(!is_android(r#"cfg(target_arch = "wasm32")"#));
64         assert!(is_android(r#"cfg(any(target_os = "linux", target_os = "android"))"#));
65         assert!(is_android(
66             r#"cfg(any(all(target_arch = "arm", target_pointer_width = "32"), target_arch = "mips", target_arch = "powerpc"))"#
67         ));
68         assert!(!is_android(
69             r#"cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown"))"#
70         ));
71         assert!(is_android("cfg(tracing_unstable)"));
72         assert!(is_android(r#"cfg(any(unix, target_os = "wasi"))"#));
73         assert!(is_android(r#"cfg(not(all(target_arch = "arm", target_os = "none")))"#))
74     }
75 }
76