Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deduplicate all (recursively) added runtime libraries #333

Merged
merged 4 commits into from
Sep 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cargo-apk/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- Upgrade to latest `ndk-build` to deduplicate libraries before packaging them into the APK. ([#333](https://github.com/rust-windowing/android-ndk-rs/pull/333))

# 0.9.3 (2022-07-05)

- Allow configuration of alternate debug keystore location; require keystore location for release builds. ([#299](https://github.com/rust-windowing/android-ndk-rs/pull/299))
Expand Down
4 changes: 2 additions & 2 deletions cargo-apk/src/apk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ impl<'a> ApkBuilder<'a> {
manifest,
disable_aapt_compression: is_debug_profile,
};
let apk = config.create_apk()?;
let mut apk = config.create_apk()?;

for target in &self.build_targets {
let triple = target.rust_triple();
Expand Down Expand Up @@ -231,7 +231,7 @@ impl<'a> ApkBuilder<'a> {
(None, false) => return Err(Error::MissingReleaseKey(profile_name.to_owned())),
};

Ok(apk.align()?.sign(signing_key)?)
Ok(apk.add_pending_libs_and_align()?.sign(signing_key)?)
}

pub fn run(&self, artifact: &Artifact) -> Result<(), Error> {
Expand Down
2 changes: 2 additions & 0 deletions ndk-build/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Unreleased

- **Breaking:** Postpone APK library packaging until before zip alignment, to deduplicate possibly overlapping entries. ([#333](https://github.com/rust-windowing/android-ndk-rs/pull/333))

# 0.7.0 (2022-07-05)

- Fix NDK r23 `-lgcc` workaround for target directories containing spaces. ([#298](https://github.com/rust-windowing/android-ndk-rs/pull/298))
Expand Down
58 changes: 36 additions & 22 deletions ndk-build/src/apk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::error::NdkError;
use crate::manifest::AndroidManifest;
use crate::ndk::{Key, Ndk};
use crate::target::Target;
use std::collections::HashSet;
use std::ffi::OsStr;
use std::fs;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -68,24 +69,30 @@ impl ApkConfig {
return Err(NdkError::CmdFailed(aapt));
}

Ok(UnalignedApk(self))
Ok(UnalignedApk {
config: self,
pending_libs: HashSet::default(),
})
}
}

pub struct UnalignedApk<'a>(&'a ApkConfig);
pub struct UnalignedApk<'a> {
config: &'a ApkConfig,
pending_libs: HashSet<String>,
}

impl<'a> UnalignedApk<'a> {
pub fn config(&self) -> &ApkConfig {
self.0
self.config
}

pub fn add_lib(&self, path: &Path, target: Target) -> Result<(), NdkError> {
pub fn add_lib(&mut self, path: &Path, target: Target) -> Result<(), NdkError> {
if !path.exists() {
return Err(NdkError::PathNotFound(path.into()));
}
let abi = target.android_abi();
let lib_path = Path::new("lib").join(abi).join(path.file_name().unwrap());
let out = self.0.build_dir.join(&lib_path);
let out = self.config.build_dir.join(&lib_path);
std::fs::create_dir_all(out.parent().unwrap())?;
std::fs::copy(path, out)?;

Expand All @@ -94,23 +101,13 @@ impl<'a> UnalignedApk<'a> {
// Otherwise, it results in a runtime error when loading the NativeActivity `.so` library.
let lib_path_unix = lib_path.to_str().unwrap().replace('\\', "/");

let mut aapt = self.0.build_tool(bin!("aapt"))?;
aapt.arg("add");

if self.0.disable_aapt_compression {
aapt.arg("-0").arg("");
}

aapt.arg(self.0.unaligned_apk()).arg(lib_path_unix);
self.pending_libs.insert(lib_path_unix);

if !aapt.status()?.success() {
return Err(NdkError::CmdFailed(aapt));
}
Ok(())
}

pub fn add_runtime_libs(
&self,
&mut self,
path: &Path,
target: Target,
search_paths: &[&Path],
Expand All @@ -126,18 +123,35 @@ impl<'a> UnalignedApk<'a> {
Ok(())
}

pub fn align(self) -> Result<UnsignedApk<'a>, NdkError> {
let mut zipalign = self.0.build_tool(bin!("zipalign"))?;
pub fn add_pending_libs_and_align(self) -> Result<UnsignedApk<'a>, NdkError> {
let mut aapt = self.config.build_tool(bin!("aapt"))?;
aapt.arg("add");

if self.config.disable_aapt_compression {
aapt.arg("-0").arg("");
}

aapt.arg(self.config.unaligned_apk());

for lib_path_unix in self.pending_libs {
aapt.arg(lib_path_unix);
}

if !aapt.status()?.success() {
return Err(NdkError::CmdFailed(aapt));
}

let mut zipalign = self.config.build_tool(bin!("zipalign"))?;
zipalign
.arg("-f")
.arg("-v")
.arg("4")
.arg(self.0.unaligned_apk())
.arg(self.0.apk());
.arg(self.config.unaligned_apk())
.arg(self.config.apk());
if !zipalign.status()?.success() {
return Err(NdkError::CmdFailed(zipalign));
}
Ok(UnsignedApk(self.0))
Ok(UnsignedApk(self.config))
}
}

Expand Down
2 changes: 1 addition & 1 deletion ndk-build/src/readelf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::process::Command;

impl<'a> UnalignedApk<'a> {
pub fn add_lib_recursively(
&self,
&mut self,
lib: &Path,
target: Target,
search_paths: &[&Path],
Expand Down