Skip to content

Commit

Permalink
Read environment variables from .cargo/config.toml's [env] section
Browse files Browse the repository at this point in the history
  • Loading branch information
MarijnS95 committed Mar 2, 2022
1 parent 18d53c9 commit c05848c
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 19 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ members = [
"ndk-sys",
"cargo-apk",
]

[patch.crates-io]
# https://github.com/dvc94ch/cargo-subcommand/pull/12
cargo-subcommand = { git = "https://github.com/dvc94ch/cargo-subcommand", rev = "55269e6" }
1 change: 1 addition & 0 deletions cargo-apk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- Default `target_sdk_version` to `30` or lower (instead of the highest supported SDK version by the detected NDK toolchain)
for more consistent interaction with Android backwards compatibility handling and its increasingly strict usage rules:
https://developer.android.com/distribute/best-practices/develop/target-sdk
- Read environment variables from `.cargo/config.toml`'s `[env]` section.

# 0.8.2 (2021-11-22)

Expand Down
23 changes: 19 additions & 4 deletions cargo-apk/src/apk.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::error::Error;
use crate::manifest::Manifest;
use cargo_subcommand::{Artifact, CrateType, Profile, Subcommand};
use cargo_subcommand::{Artifact, CrateType, LocalizedConfig, Profile, Subcommand};
use ndk_build::apk::{Apk, ApkConfig};
use ndk_build::cargo::{cargo_ndk, VersionCode};
use ndk_build::cargo::{cargo_ndk, Env, VersionCode};
use ndk_build::dylibs::get_libs_search_paths;
use ndk_build::error::NdkError;
use ndk_build::manifest::MetaData;
use ndk_build::ndk::Ndk;
use ndk_build::target::Target;
use std::path::PathBuf;
use std::process::Command;
use std::sync::Arc;

pub struct ApkBuilder<'a> {
cmd: &'a Subcommand,
Expand All @@ -19,9 +20,23 @@ pub struct ApkBuilder<'a> {
build_targets: Vec<Target>,
}

struct ConfigEnv(Option<LocalizedConfig>);
impl Env for ConfigEnv {
fn var(&self, key: &str) -> std::result::Result<std::borrow::Cow<'_, str>, std::env::VarError> {
match &self.0 {
Some(config) => config
.resolve_env(key)
// IO error is currently only returned when path canonicalization fails
.expect("Failed to resolve environment variable")
.ok_or(std::env::VarError::NotPresent),
None => std::env::var(key).map(|s| s.into()),
}
}
}

impl<'a> ApkBuilder<'a> {
pub fn from_subcommand(cmd: &'a Subcommand) -> Result<Self, Error> {
let ndk = Ndk::from_env()?;
let ndk = Ndk::from_env(Arc::new(ConfigEnv(cmd.config().cloned())))?;
let mut manifest = Manifest::parse_from_toml(cmd.manifest())?;
let build_targets = if let Some(target) = cmd.target() {
vec![Target::from_rust_triple(target)?]
Expand Down Expand Up @@ -224,7 +239,7 @@ impl<'a> ApkBuilder<'a> {
}

pub fn default(&self) -> Result<(), Error> {
let ndk = Ndk::from_env()?;
let ndk = Ndk::from_env(Arc::new(ConfigEnv(None)))?;
for target in &self.build_targets {
let mut cargo = cargo_ndk(&ndk, *target, self.min_sdk_version())?;
cargo.args(self.cmd.args());
Expand Down
1 change: 1 addition & 0 deletions ndk-build/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Default `target_sdk_version` to `30` or lower (instead of the highest supported SDK version by the detected NDK toolchain)
for more consistent interaction with Android backwards compatibility handling and its increasingly strict usage rules:
https://developer.android.com/distribute/best-practices/develop/target-sdk
- **Breaking:** `Ndk` now requires a struct implementing `Env` to read environment variables from.

# 0.4.3 (2021-11-22)

Expand Down
4 changes: 4 additions & 0 deletions ndk-build/src/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ use crate::ndk::Ndk;
use crate::target::Target;
use std::process::Command;

pub trait Env {
fn var(&self, key: &str) -> std::result::Result<std::borrow::Cow<'_, str>, std::env::VarError>;
}

pub fn cargo_ndk(ndk: &Ndk, target: Target, sdk_version: u32) -> Result<Command, NdkError> {
let triple = target.rust_triple();
let mut cargo = Command::new("cargo");
Expand Down
46 changes: 31 additions & 15 deletions ndk-build/src/ndk.rs
Original file line number Diff line number Diff line change
@@ -1,47 +1,51 @@
use crate::cargo::Env;
use crate::error::NdkError;
use crate::target::Target;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::Arc;

#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone)]
pub struct Ndk {
sdk_path: PathBuf,
ndk_path: PathBuf,
build_tools_version: String,
build_tag: u32,
platforms: Vec<u32>,
env: Arc<dyn Env>,
}

impl Ndk {
pub fn from_env() -> Result<Self, NdkError> {
pub fn from_env(env: Arc<dyn Env>) -> Result<Self, NdkError> {
let sdk_path = {
let mut sdk_path = std::env::var("ANDROID_HOME").ok();
let mut sdk_path = env.var("ANDROID_HOME").ok();
if sdk_path.is_some() {
println!(
"Warning: You use environment variable ANDROID_HOME that is deprecated. \
Please, remove it and use ANDROID_SDK_ROOT instead. Now ANDROID_HOME is used"
);
}
if sdk_path.is_none() {
sdk_path = std::env::var("ANDROID_SDK_ROOT").ok();
sdk_path = env.var("ANDROID_SDK_ROOT").ok();
}

PathBuf::from(sdk_path.ok_or(NdkError::SdkNotFound)?)
PathBuf::from(sdk_path.ok_or(NdkError::SdkNotFound)?.as_ref())
};

let ndk_path = {
let ndk_path = std::env::var("ANDROID_NDK_ROOT")
let ndk_path = env
.var("ANDROID_NDK_ROOT")
.ok()
.or_else(|| std::env::var("ANDROID_NDK_PATH").ok())
.or_else(|| std::env::var("ANDROID_NDK_HOME").ok())
.or_else(|| std::env::var("NDK_HOME").ok());
.or_else(|| env.var("ANDROID_NDK_PATH").ok())
.or_else(|| env.var("ANDROID_NDK_HOME").ok())
.or_else(|| env.var("NDK_HOME").ok());

// default ndk installation path
if ndk_path.is_none() && sdk_path.join("ndk-bundle").exists() {
sdk_path.join("ndk-bundle")
} else {
PathBuf::from(ndk_path.ok_or(NdkError::NdkNotFound)?)
PathBuf::from(ndk_path.ok_or(NdkError::NdkNotFound)?.as_ref())
}
};

Expand Down Expand Up @@ -116,6 +120,7 @@ impl Ndk {
build_tools_version,
build_tag,
platforms,
env,
})
}

Expand Down Expand Up @@ -191,7 +196,7 @@ impl Ndk {
}

pub fn toolchain_dir(&self) -> Result<PathBuf, NdkError> {
let host_os = std::env::var("HOST").ok();
let host_os = self.env.var("HOST").ok();
let host_contains = |s| host_os.as_ref().map(|h| h.contains(s)).unwrap_or(false);

let arch = if host_contains("linux") {
Expand All @@ -208,7 +213,7 @@ impl Ndk {
"windows"
} else {
return match host_os {
Some(host_os) => Err(NdkError::UnsupportedHost(host_os)),
Some(host_os) => Err(NdkError::UnsupportedHost(host_os.into())),
_ => Err(NdkError::UnsupportedTarget),
};
};
Expand Down Expand Up @@ -293,8 +298,10 @@ impl Ndk {
if let Ok(keytool) = which::which(bin!("keytool")) {
return Ok(Command::new(keytool));
}
if let Ok(java) = std::env::var("JAVA_HOME") {
let keytool = PathBuf::from(java).join("bin").join(bin!("keytool"));
if let Ok(java) = self.env.var("JAVA_HOME") {
let keytool = PathBuf::from(java.as_ref())
.join("bin")
.join(bin!("keytool"));
if keytool.exists() {
return Ok(Command::new(keytool));
}
Expand Down Expand Up @@ -401,7 +408,16 @@ mod tests {
#[test]
#[ignore]
fn test_detect() {
let ndk = Ndk::from_env().unwrap();
struct GlobalEnv;
impl Env for GlobalEnv {
fn var(
&self,
key: &str,
) -> std::result::Result<std::borrow::Cow<'_, str>, std::env::VarError> {
std::env::var(key).map(|s| s.into())
}
}
let ndk = Ndk::from_env(Arc::new(GlobalEnv)).unwrap();
assert_eq!(ndk.build_tools_version(), "29.0.2");
assert_eq!(ndk.platforms(), &[29, 28]);
}
Expand Down

0 comments on commit c05848c

Please sign in to comment.