Skip to content

android: Probe whether dl_iterate_phdr is defined #228

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

Merged
merged 1 commit into from
Jul 17, 2019
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
74 changes: 74 additions & 0 deletions ci/android-sdk.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env sh
# Copyright 2016 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.

set -ex

# Prep the SDK and emulator
#
# Note that the update process requires that we accept a bunch of licenses, and
# we can't just pipe `yes` into it for some reason, so we take the same strategy
# located in https://github.com/appunite/docker by just wrapping it in a script
# which apparently magically accepts the licenses.

SDK=4333796
mkdir sdk
curl --retry 20 https://dl.google.com/android/repository/sdk-tools-linux-${SDK}.zip -O
unzip -q -d sdk sdk-tools-linux-${SDK}.zip

case "$1" in
arm | armv7)
api=24
image="system-images;android-${api};google_apis;armeabi-v7a"
;;
aarch64)
api=24
image="system-images;android-${api};google_apis;arm64-v8a"
;;
i686)
api=28
image="system-images;android-${api};default;x86"
;;
x86_64)
api=28
image="system-images;android-${api};default;x86_64"
;;
*)
echo "invalid arch: $1"
exit 1
;;
esac;

# Try to fix warning about missing file.
# See https://askubuntu.com/a/1078784
mkdir -p /root/.android/
echo '### User Sources for Android SDK Manager' >> /root/.android/repositories.cfg
echo '#Fri Nov 03 10:11:27 CET 2017 count=0' >> /root/.android/repositories.cfg

# Print all available packages
# yes | ./sdk/tools/bin/sdkmanager --list --verbose

# --no_https avoids
# javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: No trusted certificate found
#
# | grep -v = || true removes the progress bar output from the sdkmanager
# which produces an insane amount of output.
yes | ./sdk/tools/bin/sdkmanager --licenses --no_https | grep -v = || true
yes | ./sdk/tools/bin/sdkmanager --no_https \
"emulator" \
"platform-tools" \
"platforms;android-${api}" \
"${image}" | grep -v = || true

echo "no" |
./sdk/tools/bin/avdmanager create avd \
--name "${1}" \
--package "${image}" | grep -v = || true

23 changes: 21 additions & 2 deletions ci/docker/arm-linux-androideabi/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,27 @@ RUN apt-get update && apt-get install -y --no-install-recommends \

COPY android-ndk.sh /
RUN /android-ndk.sh arm
ENV PATH=$PATH:/android-toolchain/bin
WORKDIR /android
COPY android-sdk.sh /android/sdk.sh
RUN ./sdk.sh arm
RUN mv /root/.android /tmp
RUN chmod 777 -R /tmp/.android
RUN chmod 755 /android/sdk/tools/* /android/sdk/emulator/qemu/linux-x86_64/*
ENV PATH=$PATH:/android-toolchain/bin:/android/sdk/platform-tools

# TODO: run tests in an emulator eventually
ENV CARGO_TARGET_ARM_LINUX_ANDROIDEABI_LINKER=arm-linux-androideabi-gcc \
CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER="true"
CARGO_TARGET_ARM_LINUX_ANDROIDEABI_RUNNER=/tmp/runtest \
HOME=/tmp

ADD runtest-android.rs /tmp/runtest.rs
ENTRYPOINT [ \
"bash", \
"-c", \
# set SHELL so android can detect a 64bits system, see
# http://stackoverflow.com/a/41789144
"SHELL=/bin/dash /android/sdk/emulator/emulator @arm -no-window & \
/rust/bin/rustc /tmp/runtest.rs -o /tmp/runtest && \
exec \"$@\"", \
"--" \
]
50 changes: 50 additions & 0 deletions ci/runtest-android.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use std::env;
use std::process::Command;
use std::path::{Path, PathBuf};

fn main() {
let args = env::args_os()
.skip(1)
.filter(|arg| arg != "--quiet")
.collect::<Vec<_>>();
assert_eq!(args.len(), 1);
let test = PathBuf::from(&args[0]);
let dst = Path::new("/data/local/tmp").join(test.file_name().unwrap());

println!("waiting for device to come online...");
let status = Command::new("adb")
.arg("wait-for-device")
.status()
.expect("failed to run: adb wait-for-device");
assert!(status.success());

println!("pushing executable...");
let status = Command::new("adb")
.arg("push")
.arg(&test)
.arg(&dst)
.status()
.expect("failed to run: adb pushr");
assert!(status.success());

println!("executing tests...");
let output = Command::new("adb")
.arg("shell")
.arg(&dst)
.output()
.expect("failed to run: adb shell");
assert!(status.success());

println!("status: {}\nstdout ---\n{}\nstderr ---\n{}",
output.status,
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr));

let stdout = String::from_utf8_lossy(&output.stdout);
stdout.lines().find(|l|
(l.starts_with("PASSED ") && l.contains(" tests")) ||
l.starts_with("test result: ok")
).unwrap_or_else(|| {
panic!("failed to find successful test run");
});
}
34 changes: 32 additions & 2 deletions crates/backtrace-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ fn main() {
build.define("BACKTRACE_SUPPORTS_DATA", "0");

File::create(out_dir.join("config.h")).unwrap();
if !target.contains("apple-ios")
if target.contains("android") {
maybe_enable_dl_iterate_phdr_android(&mut build);
} else if !target.contains("apple-ios")
&& !target.contains("solaris")
&& !target.contains("redox")
&& !target.contains("android")
&& !target.contains("haiku")
&& !target.contains("vxworks")
{
Expand Down Expand Up @@ -122,3 +123,32 @@ fn main() {

build.compile("backtrace");
}

// The `dl_iterate_phdr` API was added in Android API 21+ (according to #227),
// so if we can dynamically detect an appropriately configured C compiler for
// that then let's enable the `dl_iterate_phdr` API, otherwise Android just
// won't have any information.
fn maybe_enable_dl_iterate_phdr_android(build: &mut cc::Build) {
let expansion = cc::Build::new().file("src/android-api.c").expand();
let expansion = match std::str::from_utf8(&expansion) {
Ok(s) => s,
Err(_) => return,
};
println!("expanded android version detection:\n{}", expansion);
let marker = "APIVERSION";
let i = match expansion.find(marker) {
Some(i) => i,
None => return,
};
let version = match expansion[i + marker.len() + 1..].split_whitespace().next() {
Some(s) => s,
None => return,
};
let version = match version.parse::<u32>() {
Ok(n) => n,
Err(_) => return,
};
if version >= 21 {
build.define("HAVE_DL_ITERATE_PHDR", "1");
}
}
4 changes: 4 additions & 0 deletions crates/backtrace-sys/src/android-api.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Used from the build script to detect the value of the `__ANDROID_API__`
// builtin #define

APIVERSION __ANDROID_API__