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