Vendor OpenSSL on android with google prebuilt libs (#4511)
* vendor android openssl * add fallback * dont panic
This commit is contained in:
1 parent
89834bc1b3
commit
79e7739bee
8 files changed
+125
-42
No files matched your search
Generated
-13
@@ -5321,7 +5321,6 @@ dependencies = [
|
|||||||
"ndk-sys 0.6.0+11769913",
|
"ndk-sys 0.6.0+11769913",
|
||||||
"objc",
|
"objc",
|
||||||
"objc_id",
|
"objc_id",
|
||||||
"openssl",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"reqwest 0.12.22",
|
"reqwest 0.12.22",
|
||||||
@@ -5411,7 +5410,6 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.3",
|
||||||
"http-range",
|
"http-range",
|
||||||
"openssl",
|
|
||||||
"ouroboros",
|
"ouroboros",
|
||||||
"rand 0.9.1",
|
"rand 0.9.1",
|
||||||
"reqwest 0.12.22",
|
"reqwest 0.12.22",
|
||||||
@@ -5668,7 +5666,6 @@ dependencies = [
|
|||||||
"dioxus-native-dom",
|
"dioxus-native-dom",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"openssl",
|
|
||||||
"rustc-hash 2.1.1",
|
"rustc-hash 2.1.1",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -11614,15 +11611,6 @@ version = "0.1.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "openssl-src"
|
|
||||||
version = "300.5.1+3.5.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "735230c832b28c000e3bc117119e6466a663ec73506bc0a9907ea4187508e42a"
|
|
||||||
dependencies = [
|
|
||||||
"cc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.109"
|
version = "0.9.109"
|
||||||
@@ -11631,7 +11619,6 @@ checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
"openssl-src",
|
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|||||||
+1
-5
@@ -366,7 +366,7 @@ winit = { version = "0.30.11", features = ["rwh_06"] }
|
|||||||
incremental = true
|
incremental = true
|
||||||
|
|
||||||
# crank up the opt level for wasm-split-cli in dev mode
|
# crank up the opt level for wasm-split-cli in dev mode
|
||||||
# important here that lto is on and the debug symbols are present (since they're used by wasm-opt)a
|
# important here that lto is on and the debug symbols are present (since they're used by wasm-opt)
|
||||||
[profile.wasm-split-release]
|
[profile.wasm-split-release]
|
||||||
inherits = "release"
|
inherits = "release"
|
||||||
opt-level = 'z'
|
opt-level = 'z'
|
||||||
@@ -449,10 +449,6 @@ tokio = { version = "1.46", default-features = false, features = ["sync", "macro
|
|||||||
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
|
||||||
tokio = { version = "1.46", features = ["full"] }
|
tokio = { version = "1.46", features = ["full"] }
|
||||||
|
|
||||||
# force vendored openssl on android
|
|
||||||
[target.'cfg(target_os = "android")'.dev-dependencies]
|
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
|
||||||
|
|
||||||
# To make most examples faster to compile, we split out assets and http-related stuff
|
# To make most examples faster to compile, we split out assets and http-related stuff
|
||||||
# This trims off like 270 dependencies, leading to a significant speedup in compilation time
|
# This trims off like 270 dependencies, leading to a significant speedup in compilation time
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
This folder contains prebuilt versions of android crates to make cross-compiling easier.
|
||||||
|
|
||||||
|
We use the official prebuilds distributed by google.
|
||||||
|
|
||||||
|
You can find the full set of prebuilt libraries that google distributes here:
|
||||||
|
|
||||||
|
https://maven.google.com/web/index.html?q=com.android.ndk.thirdparty#com.android.ndk.thirdparty
|
||||||
|
|
||||||
|
The version included in `dx` is downloaded from here:
|
||||||
|
|
||||||
|
https://maven.google.com/web/index.html?q=com.android.ndk.thirdparty#com.android.ndk.thirdparty:openssl:1.1.1q-beta-1
|
||||||
|
|
||||||
|
The SHA of the `.aar` file from google and `dx` are different. The Rust openssl-sys crate expects libcrypto and libssl to be in the same folder, but the `.aar` that google distributes splits the two libraries into two different folders. I (jon) have simply merged the folders together and then re-packed the folder as a `.tar.gz`.
|
||||||
Binary file not shown.
@@ -1147,6 +1147,10 @@ impl BuildRequest {
|
|||||||
async fn write_frameworks(&self, _ctx: &BuildContext, direct_rustc: &RustcArgs) -> Result<()> {
|
async fn write_frameworks(&self, _ctx: &BuildContext, direct_rustc: &RustcArgs) -> Result<()> {
|
||||||
let framework_dir = self.frameworks_folder();
|
let framework_dir = self.frameworks_folder();
|
||||||
|
|
||||||
|
// We have some prebuilt stuff that needs to be copied into the framework dir
|
||||||
|
let openssl_dir = AndroidTools::openssl_lib_dir(&self.triple);
|
||||||
|
let openssl_dir_disp = openssl_dir.display().to_string();
|
||||||
|
|
||||||
for arg in &direct_rustc.link_args {
|
for arg in &direct_rustc.link_args {
|
||||||
// todo - how do we handle windows dlls? we don't want to bundle the system dlls
|
// todo - how do we handle windows dlls? we don't want to bundle the system dlls
|
||||||
// for now, we don't do anything with dlls, and only use .dylibs and .so files
|
// for now, we don't do anything with dlls, and only use .dylibs and .so files
|
||||||
@@ -1180,13 +1184,25 @@ impl BuildRequest {
|
|||||||
|
|
||||||
// On android, the c++_shared flag means we need to copy the libc++_shared.so precompiled
|
// On android, the c++_shared flag means we need to copy the libc++_shared.so precompiled
|
||||||
// library to the jniLibs folder
|
// library to the jniLibs folder
|
||||||
if arg.contains("-lc++_shared") && self.bundle == BundleFormat::Android {
|
if self.bundle == BundleFormat::Android && arg.contains("-lc++_shared") {
|
||||||
std::fs::copy(
|
std::fs::copy(
|
||||||
self.workspace.android_tools()?.libcpp_shared(&self.triple),
|
self.workspace.android_tools()?.libcpp_shared(&self.triple),
|
||||||
framework_dir.join("libc++_shared.so"),
|
framework_dir.join("libc++_shared.so"),
|
||||||
)
|
)
|
||||||
.with_context(|| "Failed to copy libc++_shared.so into bundle")?;
|
.with_context(|| "Failed to copy libc++_shared.so into bundle")?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy over libssl and libcrypto if they are present in the link args
|
||||||
|
if self.bundle == BundleFormat::Android && arg.contains(openssl_dir_disp.as_str()) {
|
||||||
|
let libssl = openssl_dir.join("libssl.so");
|
||||||
|
let libcrypto = openssl_dir.join("libcrypto.so");
|
||||||
|
std::fs::copy(&libssl, framework_dir.join("libssl.so")).with_context(|| {
|
||||||
|
format!("Failed to copy libssl.so into bundle from {libssl:?}")
|
||||||
|
})?;
|
||||||
|
std::fs::copy(&libcrypto, framework_dir.join("libcrypto.so")).with_context(
|
||||||
|
|| format!("Failed to copy libcrypto.so into bundle from {libcrypto:?}"),
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -2590,17 +2606,21 @@ impl BuildRequest {
|
|||||||
|
|
||||||
// choose the clang target with the highest version
|
// choose the clang target with the highest version
|
||||||
// Should we filter for only numbers?
|
// Should we filter for only numbers?
|
||||||
let clang_builtins_target = std::fs::read_dir(clang_folder)
|
let clang_rt = std::fs::read_dir(&clang_folder)
|
||||||
.expect("Unable to get clang target directory")
|
.map(|dir| {
|
||||||
.filter_map(|a| a.ok())
|
let clang_builtins_target = dir
|
||||||
.max_by(|a, b| a.file_name().cmp(&b.file_name()))
|
.filter_map(|a| a.ok())
|
||||||
.expect("Unable to get clang target")
|
.max_by(|a, b| a.file_name().cmp(&b.file_name()))
|
||||||
.path();
|
.map(|s| s.path())
|
||||||
let clang_rt = format!(
|
.unwrap_or_else(|| clang_folder.join("clang"));
|
||||||
"-L{} -lstatic=clang_rt.builtins-{}-android",
|
|
||||||
clang_builtins_target.join("lib").join("linux").display(),
|
format!(
|
||||||
rt_builtins(&triple)
|
"-L{} -lstatic=clang_rt.builtins-{}-android",
|
||||||
);
|
clang_builtins_target.join("lib").join("linux").display(),
|
||||||
|
rt_builtins(&triple)
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let extra_include: String = format!(
|
let extra_include: String = format!(
|
||||||
"{}/usr/include/{}",
|
"{}/usr/include/{}",
|
||||||
@@ -2614,6 +2634,17 @@ impl BuildRequest {
|
|||||||
extra_include
|
extra_include
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Load up the OpenSSL environment variables, using our defaults if not set.
|
||||||
|
// if the user specifies `/vendor`, then they get vendored, unless OPENSSL_NO_VENDOR is passed (implicitly...)
|
||||||
|
let openssl_lib_dir = std::env::var("OPENSSL_LIB_DIR")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.unwrap_or_else(|_| AndroidTools::openssl_lib_dir(&self.triple));
|
||||||
|
let openssl_include_dir = std::env::var("OPENSSL_INCLUDE_DIR")
|
||||||
|
.map(PathBuf::from)
|
||||||
|
.unwrap_or_else(|_| AndroidTools::openssl_include_dir());
|
||||||
|
let openssl_libs =
|
||||||
|
std::env::var("OPENSSL_LIBS").unwrap_or_else(|_| "ssl:crypto".to_string());
|
||||||
|
|
||||||
for env in [
|
for env in [
|
||||||
(cc_key, target_cc.clone().into_os_string()),
|
(cc_key, target_cc.clone().into_os_string()),
|
||||||
(cflags_key, target_cflags.into()),
|
(cflags_key, target_cflags.into()),
|
||||||
@@ -2651,6 +2682,15 @@ impl BuildRequest {
|
|||||||
linker.into_os_string(),
|
linker.into_os_string(),
|
||||||
),
|
),
|
||||||
("ANDROID_NDK_ROOT".to_string(), ndk_home.into_os_string()),
|
("ANDROID_NDK_ROOT".to_string(), ndk_home.into_os_string()),
|
||||||
|
(
|
||||||
|
"OPENSSL_LIB_DIR".to_string(),
|
||||||
|
openssl_lib_dir.into_os_string(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"OPENSSL_INCLUDE_DIR".to_string(),
|
||||||
|
openssl_include_dir.into_os_string(),
|
||||||
|
),
|
||||||
|
("OPENSSL_LIBS".to_string(), openssl_libs.into()),
|
||||||
// Set the wry env vars - this is where wry will dump its kotlin files.
|
// Set the wry env vars - this is where wry will dump its kotlin files.
|
||||||
// Their setup is really annyoing and requires us to hardcode `dx` to specific versions of tao/wry.
|
// Their setup is really annyoing and requires us to hardcode `dx` to specific versions of tao/wry.
|
||||||
(
|
(
|
||||||
@@ -4684,6 +4724,11 @@ __wbg_init({{module_or_path: "/{}/{wasm_path}"}}).then((wasm) => {{
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
// We want to copy over the prebuilt OpenSSL binaries to ~/.dx/prebuilt/openssl-<version>
|
||||||
|
if self.bundle == BundleFormat::Android {
|
||||||
|
AndroidTools::unpack_prebuilt_openssl()?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use crate::Result;
|
||||||
|
use anyhow::Context;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::{path::PathBuf, sync::Arc};
|
use std::{path::PathBuf, sync::Arc};
|
||||||
use target_lexicon::{
|
use target_lexicon::{
|
||||||
@@ -301,6 +303,56 @@ impl AndroidTools {
|
|||||||
_ => rust_target,
|
_ => rust_target,
|
||||||
}) as _
|
}) as _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn openssl_prebuilt_aar() -> &'static [u8] {
|
||||||
|
include_bytes!("../../assets/android/prebuilt/openssl-1.1.1q-beta-1.tar.gz")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn openssl_prebuilt_dest() -> PathBuf {
|
||||||
|
crate::Workspace::dioxus_data_dir()
|
||||||
|
.join("prebuilt")
|
||||||
|
.join("openssl-1.1.1q-beta-1")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn openssl_lib_dir(arch: &Triple) -> PathBuf {
|
||||||
|
let libs_dir = Self::openssl_prebuilt_dest().join("ssl").join("libs");
|
||||||
|
|
||||||
|
match arch.architecture {
|
||||||
|
Architecture::Arm(_) => libs_dir.join("android.armeabi-v7a"),
|
||||||
|
Architecture::Aarch64(_) => libs_dir.join("android.arm64-v8a"),
|
||||||
|
Architecture::X86_32(_) => libs_dir.join("android.x86"),
|
||||||
|
Architecture::X86_64 => libs_dir.join("android.x86_64"),
|
||||||
|
_ => libs_dir.join("android.arm64-v8a"), // Default to arm64-v8a
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn openssl_include_dir() -> PathBuf {
|
||||||
|
Self::openssl_prebuilt_dest().join("ssl").join("include")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unzip the prebuilt OpenSSL AAR file into the `.dx/prebuilt/openssl-<version>` directory
|
||||||
|
pub(crate) fn unpack_prebuilt_openssl() -> Result<()> {
|
||||||
|
let raw_aar = AndroidTools::openssl_prebuilt_aar();
|
||||||
|
let aar_dest = AndroidTools::openssl_prebuilt_dest();
|
||||||
|
|
||||||
|
if aar_dest.exists() {
|
||||||
|
tracing::trace!("Prebuilt OpenSSL already exists at {:?}", aar_dest);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::create_dir_all(aar_dest.parent().context("no parent for aar")?)
|
||||||
|
.context("failed to create prebuilt OpenSSL directory")?;
|
||||||
|
|
||||||
|
// Unpack the entire tar.gz file into the destination directory
|
||||||
|
let mut archive = tar::Archive::new(flate2::read::GzDecoder::new(raw_aar as &[u8]));
|
||||||
|
archive
|
||||||
|
.unpack(aar_dest.parent().context("no parent for aar dest")?)
|
||||||
|
.context("failed to unpack prebuilt OpenSSL archive")?;
|
||||||
|
|
||||||
|
tracing::debug!("Unpacked prebuilt OpenSSL to {:?}", aar_dest);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn var_or_debug(name: &str) -> Option<PathBuf> {
|
fn var_or_debug(name: &str) -> Option<PathBuf> {
|
||||||
|
|||||||
@@ -78,11 +78,6 @@ ndk = { version = "0.9.0" }
|
|||||||
ndk-sys = { version = "0.6.0" }
|
ndk-sys = { version = "0.6.0" }
|
||||||
ndk-context = { version = "0.1.1" }
|
ndk-context = { version = "0.1.1" }
|
||||||
|
|
||||||
# The `openssl` dependency generally does not know how to cross-compile for Android. To make the lives
|
|
||||||
# of our users easier, we automatically enable the `openssl` feature when building for Android.
|
|
||||||
# Feature are additive, so users will need to "subtract" this feature if they do not want it.
|
|
||||||
openssl = { version = "0.10", features = ["vendored"], optional = true }
|
|
||||||
|
|
||||||
# use native tls on other platforms
|
# use native tls on other platforms
|
||||||
[target.'cfg(not(target_os = "android"))'.dependencies]
|
[target.'cfg(not(target_os = "android"))'.dependencies]
|
||||||
tungstenite = { workspace = true, features = ["native-tls"] }
|
tungstenite = { workspace = true, features = ["native-tls"] }
|
||||||
@@ -96,12 +91,11 @@ objc = "0.2.7"
|
|||||||
lazy-js-bundle = { workspace = true }
|
lazy-js-bundle = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["tokio_runtime", "transparent", "devtools", "openssl-vendored-android"]
|
default = ["tokio_runtime", "transparent", "devtools"]
|
||||||
tokio_runtime = ["dep:tokio"]
|
tokio_runtime = ["dep:tokio"]
|
||||||
fullscreen = ["wry/fullscreen"]
|
fullscreen = ["wry/fullscreen"]
|
||||||
devtools = ["wry/devtools", "dep:dioxus-devtools", "dioxus-signals"]
|
devtools = ["wry/devtools", "dep:dioxus-devtools", "dioxus-signals"]
|
||||||
transparent = ["wry/transparent"]
|
transparent = ["wry/transparent"]
|
||||||
openssl-vendored-android = ["openssl"]
|
|
||||||
gnu = []
|
gnu = []
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ homepage = "https://dioxuslabs.com/learn/0.6/getting_started"
|
|||||||
keywords = ["dom", "ui", "gui", "react"]
|
keywords = ["dom", "ui", "gui", "react"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["accessibility", "hot-reload", "tracing", "net", "svg", "system-fonts", "openssl-vendored-android"]
|
default = ["accessibility", "hot-reload", "tracing", "net", "svg", "system-fonts"]
|
||||||
svg = ["blitz-dom/svg", "blitz-paint/svg"]
|
svg = ["blitz-dom/svg", "blitz-paint/svg"]
|
||||||
net = ["dep:tokio", "dep:blitz-net"]
|
net = ["dep:tokio", "dep:blitz-net"]
|
||||||
accessibility = ["blitz-shell/accessibility", "blitz-dom/accessibility"]
|
accessibility = ["blitz-shell/accessibility", "blitz-dom/accessibility"]
|
||||||
tracing = ["dep:tracing", "blitz-shell/tracing", "blitz-dom/tracing"]
|
tracing = ["dep:tracing", "blitz-shell/tracing", "blitz-dom/tracing"]
|
||||||
hot-reload = ["dep:dioxus-cli-config", "dep:dioxus-devtools"]
|
hot-reload = ["dep:dioxus-cli-config", "dep:dioxus-devtools"]
|
||||||
system-fonts = ["blitz-dom/system_fonts"]
|
system-fonts = ["blitz-dom/system_fonts"]
|
||||||
openssl-vendored-android = ["openssl"]
|
|
||||||
autofocus = []
|
autofocus = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
@@ -52,9 +51,6 @@ tracing = { workspace = true, optional = true }
|
|||||||
rustc-hash = { workspace = true }
|
rustc-hash = { workspace = true }
|
||||||
futures-util = { workspace = true }
|
futures-util = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "android")'.dependencies]
|
|
||||||
openssl = { version = "0.10", features = ["vendored"], optional = true }
|
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
all-features = true
|
all-features = true
|
||||||
rustdoc-args = ["--cfg", "docsrs"]
|
rustdoc-args = ["--cfg", "docsrs"]
|
||||||
Reference in new issue
Block a user