forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
std: Add compatibility with android-9
The Gecko folks currently use Android API level 9 for their builds, so they're requesting that we move back our minimum supported API level from 18 to 9. Turns out, ABI-wise at least, there's not that many changes we need to take care of. The `ftruncate64` API appeared in android-12 and the `log2` and `log2f` APIs appeared in android-18. We can have a simple shim for `ftruncate64` which falls back on `ftruncate` and the `log2` function can be approximated with just `ln(f) / ln(2)`. This should at least get the standard library building on API level 9, although the tests aren't quite happening there just yet. As we seem to be growing a number of Android compatibility shims, they're now centralized in a common `sys::android` module.
- Loading branch information
1 parent
cfae4de
commit c31e2e7
Showing
5 changed files
with
138 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
// 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. | ||
|
||
//! Android ABI-compatibility module | ||
//! | ||
//! The ABI of Android has changed quite a bit over time, and libstd attempts to | ||
//! be both forwards and backwards compatible as much as possible. We want to | ||
//! always work with the most recent version of Android, but we also want to | ||
//! work with older versions of Android for whenever projects need to. | ||
//! | ||
//! Our current minimum supported Android version is `android-9`, e.g. Android | ||
//! with API level 9. We then in theory want to work on that and all future | ||
//! versions of Android! | ||
//! | ||
//! Some of the detection here is done at runtime via `dlopen` and | ||
//! introspection. Other times no detection is performed at all and we just | ||
//! provide a fallback implementation as some versions of Android we support | ||
//! don't have the function. | ||
//! | ||
//! You'll find more details below about why each compatibility shim is needed. | ||
#![cfg(target_os = "android")] | ||
|
||
use libc::{c_int, sighandler_t}; | ||
|
||
use io; | ||
use sys::cvt_r; | ||
|
||
// The `log2` and `log2f` functions apparently appeared in android-18, or at | ||
// least you can see they're not present in the android-17 header [1] and they | ||
// are present in android-18 [2]. | ||
// | ||
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms | ||
// /android-17/arch-arm/usr/include/math.h | ||
// [2]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms | ||
// /android-18/arch-arm/usr/include/math.h | ||
// | ||
// Note that these shims are likely less precise than directly calling `log2`, | ||
// but hopefully that should be enough for now... | ||
// | ||
// Note that mathematically, for any arbitrary `y`: | ||
// | ||
// log_2(x) = log_y(x) / log_y(2) | ||
// = log_y(x) / (1 / log_2(y)) | ||
// = log_y(x) * log_2(y) | ||
// | ||
// Hence because `ln` (log_e) is available on all Android we just choose `y = e` | ||
// and get: | ||
// | ||
// log_2(x) = ln(x) * log_2(e) | ||
|
||
#[cfg(not(test))] | ||
pub fn log2f32(f: f32) -> f32 { | ||
f.ln() * ::f32::consts::LOG2_E | ||
} | ||
|
||
#[cfg(not(test))] | ||
pub fn log2f64(f: f64) -> f64 { | ||
f.ln() * ::f64::consts::LOG2_E | ||
} | ||
|
||
// Back in the day [1] the `signal` function was just an inline wrapper | ||
// around `bsd_signal`, but starting in API level android-20 the `signal` | ||
// symbols was introduced [2]. Finally, in android-21 the API `bsd_signal` was | ||
// removed [3]. | ||
// | ||
// Basically this means that if we want to be binary compatible with multiple | ||
// Android releases (oldest being 9 and newest being 21) then we need to check | ||
// for both symbols and not actually link against either. | ||
// | ||
// [1]: https://chromium.googlesource.com/android_tools/+/20ee6d20/ndk/platforms | ||
// /android-18/arch-arm/usr/include/signal.h | ||
// [2]: https://chromium.googlesource.com/android_tools/+/fbd420/ndk_experimental | ||
// /platforms/android-20/arch-arm | ||
// /usr/include/signal.h | ||
// [3]: https://chromium.googlesource.com/android_tools/+/20ee6d/ndk/platforms | ||
// /android-21/arch-arm/usr/include/signal.h | ||
pub unsafe fn signal(signum: c_int, handler: sighandler_t) -> sighandler_t { | ||
weak!(fn signal(c_int, sighandler_t) -> sighandler_t); | ||
weak!(fn bsd_signal(c_int, sighandler_t) -> sighandler_t); | ||
|
||
let f = signal.get().or_else(|| bsd_signal.get()); | ||
let f = f.expect("neither `signal` nor `bsd_signal` symbols found"); | ||
f(signum, handler) | ||
} | ||
|
||
// The `ftruncate64` symbol apparently appeared in android-12, so we do some | ||
// dynamic detection to see if we can figure out whether `ftruncate64` exists. | ||
// | ||
// If it doesn't we just fall back to `ftruncate`, generating an error for | ||
// too-large values. | ||
pub fn ftruncate64(fd: c_int, size: u64) -> io::Result<()> { | ||
weak!(fn ftruncate64(c_int, i64) -> c_int); | ||
|
||
extern { | ||
fn ftruncate(fd: c_int, off: i32) -> c_int; | ||
} | ||
|
||
unsafe { | ||
match ftruncate64.get() { | ||
Some(f) => cvt_r(|| f(fd, size as i64)).map(|_| ()), | ||
None => { | ||
if size > i32::max_value() as u64 { | ||
Err(io::Error::new(io::ErrorKind::InvalidInput, | ||
"cannot truncate >2GB")) | ||
} else { | ||
cvt_r(|| ftruncate(fd, size as i32)).map(|_| ()) | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters