Skip to content

Commit

Permalink
devices/adb: Find adb executable in $ANDROID_HOME/$ANDROID_SDK_ROOT
Browse files Browse the repository at this point in the history
`adb` is not always available on `PATH`, sometimes it is installed only
via the SDK.  Make sure we find it there too - after checking `PATH` -
via well-known SDK variables.
  • Loading branch information
MarijnS95 committed Aug 26, 2023
1 parent 05f23f9 commit 8fd72e5
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 19 deletions.
50 changes: 39 additions & 11 deletions xbuild/src/command/doctor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use anyhow::Result;
use anyhow::{bail, Result};
use std::path::PathBuf;
use std::process::Command;

#[derive(Clone, Debug)]
use crate::devices::adb::Adb;

#[derive(Debug)]
pub struct Doctor {
groups: Vec<Group>,
}
Expand Down Expand Up @@ -35,7 +37,11 @@ impl Default for Doctor {
Group {
name: "android",
checks: vec![
Check::new("adb", Some(VersionCheck::new("--version", 0, 4))),
Check::with_path(
"adb",
Adb::which(),
Some(VersionCheck::new("--version", 0, 4)),
),
Check::new("javac", Some(VersionCheck::new("--version", 0, 1))),
Check::new("java", Some(VersionCheck::new("--version", 0, 1))),
Check::new("kotlin", Some(VersionCheck::new("-version", 0, 2))),
Expand Down Expand Up @@ -77,7 +83,7 @@ impl std::fmt::Display for Doctor {
}
}

#[derive(Clone, Debug)]
#[derive(Debug)]
struct Group {
name: &'static str,
checks: Vec<Check>,
Expand Down Expand Up @@ -105,15 +111,32 @@ impl std::fmt::Display for Group {
}
}

#[derive(Clone, Copy, Debug)]
#[derive(Debug)]
struct Check {
name: &'static str,
location: Option<Result<PathBuf>>,
version: Option<VersionCheck>,
}

impl Check {
pub const fn new(name: &'static str, version: Option<VersionCheck>) -> Self {
Self { name, version }
Self {
name,
location: None,
version,
}
}

pub const fn with_path(
name: &'static str,
path: Result<PathBuf>,
version: Option<VersionCheck>,
) -> Self {
Self {
name,
location: Some(path),
version,
}
}
}

Expand All @@ -131,17 +154,22 @@ impl VersionCheck {
}

impl Check {
fn name(self) -> &'static str {
fn name(&self) -> &'static str {
self.name
}

fn path(self) -> Result<PathBuf> {
Ok(which::which(self.name)?)
fn path(&self) -> Result<PathBuf> {
Ok(match &self.location {
Some(Ok(path)) => path.clone(),
// Cannot clone the error:
Some(Err(e)) => bail!("{:?}", e),
None => which::which(self.name)?,
})
}

fn version(self) -> Result<Option<String>> {
fn version(&self) -> Result<Option<String>> {
if let Some(version) = self.version {
let output = Command::new(self.name)
let output = Command::new(self.path()?)
.args(version.arg.split(' '))
.output()?;
anyhow::ensure!(output.status.success(), "failed to run {}", self.name);
Expand Down
42 changes: 39 additions & 3 deletions xbuild/src/devices/adb.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::config::AndroidDebugConfig;
use crate::devices::{Backend, Device};
use crate::{Arch, Platform};
use anyhow::Result;
use anyhow::{Context, Result};
use apk::Apk;
use std::io::{BufRead, BufReader};
use std::path::{Path, PathBuf};
Expand All @@ -12,8 +12,44 @@ use std::time::Duration;
pub(crate) struct Adb(PathBuf);

impl Adb {
pub fn which() -> Result<Self> {
Ok(Self(which::which(exe!("adb"))?))
pub fn which() -> Result<PathBuf> {
const ADB: &str = exe!("adb");

match which::which(ADB) {
Err(which::Error::CannotFindBinaryPath) => {
let sdk_path = {
let sdk_path = std::env::var("ANDROID_SDK_ROOT").ok();
if sdk_path.is_some() {
eprintln!(
"Warning: Environment variable ANDROID_SDK_ROOT is deprecated \
(https://developer.android.com/studio/command-line/variables#envar). \
It will be used until it is unset and replaced by ANDROID_HOME."
);
}

PathBuf::from(
sdk_path
.or_else(|| std::env::var("ANDROID_HOME").ok())
.context(
"Cannot find `adb` on in PATH nor is ANDROID_HOME/ANDROID_SDK_ROOT set",
)?,
)
};

let adb_path = sdk_path.join("platform-tools").join(ADB);
anyhow::ensure!(
adb_path.exists(),
"Expected `adb` at `{}`",
adb_path.display()
);
Ok(adb_path)
}
r => r.context("Could not find `adb` in PATH"),
}
}

pub fn new() -> Result<Self> {
Ok(Self(Self::which()?))
}

fn adb(&self, device: &str) -> Command {
Expand Down
10 changes: 5 additions & 5 deletions xbuild/src/devices/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ use crate::{Arch, BuildEnv, Platform};
use anyhow::Result;
use std::path::Path;

mod adb;
mod host;
mod imd;
pub(crate) mod adb;
pub(crate) mod host;
pub(crate) mod imd;

#[derive(Clone, Debug)]
enum Backend {
Expand All @@ -31,7 +31,7 @@ impl std::str::FromStr for Device {
}
if let Some((backend, id)) = device.split_once(':') {
let backend = match backend {
"adb" => Backend::Adb(Adb::which()?),
"adb" => Backend::Adb(Adb::new()?),
"imd" => Backend::Imd(IMobileDevice::which()?),
_ => anyhow::bail!("unsupported backend {}", backend),
};
Expand All @@ -58,7 +58,7 @@ impl std::fmt::Display for Device {
impl Device {
pub fn list() -> Result<Vec<Self>> {
let mut devices = vec![Self::host()];
if let Ok(adb) = Adb::which() {
if let Ok(adb) = Adb::new() {
adb.devices(&mut devices)?;
}
if let Ok(imd) = IMobileDevice::which() {
Expand Down

0 comments on commit 8fd72e5

Please sign in to comment.