@@ -2,7 +2,7 @@ use crate::cargo::CrateType;
22use crate :: download:: DownloadManager ;
33use crate :: task:: TaskRunner ;
44use crate :: { BuildEnv , Format , Opt , Platform } ;
5- use anyhow:: { Context , Result } ;
5+ use anyhow:: { ensure , Context , Result } ;
66use apk:: Apk ;
77use appbundle:: AppBundle ;
88use appimage:: AppImage ;
@@ -71,121 +71,102 @@ pub fn build(env: &BuildEnv) -> Result<()> {
7171 }
7272 Platform :: Android => {
7373 let out = platform_dir. join ( format ! ( "{}.{}" , env. name( ) , env. target( ) . format( ) ) ) ;
74- if env. config ( ) . android ( ) . gradle {
75- crate :: gradle:: build ( env, & out) ?;
76- runner. end_verbose_task ( ) ;
77- return Ok ( ( ) ) ;
78- } else {
79- let mut apk = Apk :: new (
80- out,
81- env. config ( ) . android ( ) . manifest . clone ( ) ,
82- env. target ( ) . opt ( ) != Opt :: Debug ,
83- ) ?;
84- apk. add_res ( env. icon ( ) , & env. android_jar ( ) ) ?;
85-
86- for asset in & env. config ( ) . android ( ) . assets {
87- let path = env. cargo ( ) . package_root ( ) . join ( asset. path ( ) ) ;
88-
89- if !asset. optional ( ) || path. exists ( ) {
90- apk. add_asset ( & path, asset. alignment ( ) . to_zip_file_options ( ) ) ?
74+ ensure ! ( has_lib, "Android APKs/AABs require a library" ) ;
75+
76+ let mut libraries = vec ! [ ] ;
77+
78+ for target in env. target ( ) . compile_targets ( ) {
79+ let arch_dir = platform_dir. join ( target. arch ( ) . to_string ( ) ) ;
80+ let cargo_dir = arch_dir. join ( "cargo" ) ;
81+ let lib = env. cargo_artefact ( & cargo_dir, target, CrateType :: Cdylib ) ?;
82+
83+ let ndk = env. android_ndk ( ) ;
84+
85+ let deps_dir = {
86+ let arch_dir = if target. is_host ( ) ? {
87+ cargo_dir. to_path_buf ( )
88+ } else {
89+ cargo_dir. join ( target. rust_triple ( ) ?)
90+ } ;
91+ let opt_dir = arch_dir. join ( target. opt ( ) . to_string ( ) ) ;
92+ opt_dir. join ( "deps" )
93+ } ;
94+
95+ let mut search_paths = env
96+ . cargo ( )
97+ . lib_search_paths ( & cargo_dir, target)
98+ . with_context ( || {
99+ format ! (
100+ "Finding libraries in `{}` for {:?}" ,
101+ cargo_dir. display( ) ,
102+ target
103+ )
104+ } ) ?;
105+ search_paths. push ( deps_dir) ;
106+ let search_paths = search_paths. iter ( ) . map ( AsRef :: as_ref) . collect :: < Vec < _ > > ( ) ;
107+
108+ let ndk_sysroot_libs = ndk. join ( "usr/lib" ) . join ( target. ndk_triple ( ) ) ;
109+ let provided_libs_paths = [
110+ ndk_sysroot_libs. as_path ( ) ,
111+ & * ndk_sysroot_libs. join (
112+ // Use libraries (symbols) from the lowest NDK that is supported by the application,
113+ // to prevent inadvertently making newer APIs available:
114+ // https://developer.android.com/ndk/guides/sdk-versions
115+ env. config ( )
116+ . android ( )
117+ . manifest
118+ . sdk
119+ . min_sdk_version
120+ . unwrap ( )
121+ . to_string ( ) ,
122+ ) ,
123+ ] ;
124+
125+ let mut explicit_libs = vec ! [ lib] ;
126+
127+ // Collect the libraries the user wants to include
128+ for runtime_lib_path in env. config ( ) . runtime_libs ( env. target ( ) . platform ( ) ) {
129+ let abi_dir = env
130+ . cargo ( )
131+ . package_root ( )
132+ . join ( runtime_lib_path)
133+ . join ( target. android_abi ( ) . as_str ( ) ) ;
134+ let entries = std:: fs:: read_dir ( & abi_dir) . with_context ( || {
135+ format ! (
136+ "Runtime libraries for current ABI not found at `{}`" ,
137+ abi_dir. display( )
138+ )
139+ } ) ?;
140+ for entry in entries {
141+ let entry = entry?;
142+ let path = entry. path ( ) ;
143+ if !path. is_dir ( ) && path. extension ( ) == Some ( OsStr :: new ( "so" ) ) {
144+ explicit_libs. push ( path) ;
145+ }
91146 }
92147 }
93148
94- if has_lib {
95- for target in env. target ( ) . compile_targets ( ) {
96- let arch_dir = platform_dir. join ( target. arch ( ) . to_string ( ) ) ;
97- let cargo_dir = arch_dir. join ( "cargo" ) ;
98- let lib = env. cargo_artefact ( & cargo_dir, target, CrateType :: Cdylib ) ?;
99-
100- let ndk = env. android_ndk ( ) ;
101-
102- let deps_dir = {
103- let arch_dir = if target. is_host ( ) ? {
104- cargo_dir. to_path_buf ( )
105- } else {
106- cargo_dir. join ( target. rust_triple ( ) ?)
107- } ;
108- let opt_dir = arch_dir. join ( target. opt ( ) . to_string ( ) ) ;
109- opt_dir. join ( "deps" )
110- } ;
111-
112- let mut search_paths = env
113- . cargo ( )
114- . lib_search_paths ( & cargo_dir, target)
115- . with_context ( || {
116- format ! (
117- "Finding libraries in `{}` for {:?}" ,
118- cargo_dir. display( ) ,
119- target
120- )
121- } ) ?;
122- search_paths. push ( deps_dir) ;
123- let search_paths =
124- search_paths. iter ( ) . map ( AsRef :: as_ref) . collect :: < Vec < _ > > ( ) ;
125-
126- let ndk_sysroot_libs = ndk. join ( "usr/lib" ) . join ( target. ndk_triple ( ) ) ;
127- let provided_libs_paths = [
128- ndk_sysroot_libs. as_path ( ) ,
129- & * ndk_sysroot_libs. join (
130- // Use libraries (symbols) from the lowest NDK that is supported by the application,
131- // to prevent inadvertently making newer APIs available:
132- // https://developer.android.com/ndk/guides/sdk-versions
133- env. config ( )
134- . android ( )
135- . manifest
136- . sdk
137- . min_sdk_version
138- . unwrap ( )
139- . to_string ( ) ,
140- ) ,
141- ] ;
142-
143- let mut explicit_libs = vec ! [ lib] ;
144-
145- // Collect the libraries the user wants to include
146- for runtime_lib_path in env. config ( ) . runtime_libs ( env. target ( ) . platform ( ) ) {
147- let abi_dir = env
148- . cargo ( )
149- . package_root ( )
150- . join ( runtime_lib_path)
151- . join ( target. android_abi ( ) . android_abi ( ) ) ;
152- let entries = std:: fs:: read_dir ( & abi_dir) . with_context ( || {
153- format ! (
154- "Runtime libraries for current ABI not found at `{}`" ,
155- abi_dir. display( )
156- )
157- } ) ?;
158- for entry in entries {
159- let entry = entry?;
160- let path = entry. path ( ) ;
161- if !path. is_dir ( ) && path. extension ( ) == Some ( OsStr :: new ( "so" ) ) {
162- explicit_libs. push ( path) ;
163- }
164- }
165- }
149+ // Collect the names of libraries provided by the user, and assume these
150+ // are available for other dependencies to link to, too.
151+ let mut included_libs = explicit_libs
152+ . iter ( )
153+ . map ( |p| p. file_name ( ) . unwrap ( ) . to_owned ( ) )
154+ . collect :: < HashSet < _ > > ( ) ;
166155
167- // Collect the names of libraries provided by the user, and assume these
168- // are available for other dependencies to link to, too.
169- let mut included_libs = explicit_libs
170- . iter ( )
171- . map ( |p| p. file_name ( ) . unwrap ( ) . to_owned ( ) )
172- . collect :: < HashSet < _ > > ( ) ;
173-
174- // Collect the names of all libraries that are available on Android
175- for provided_libs_path in provided_libs_paths {
176- included_libs
177- . extend ( xcommon:: llvm:: find_libs_in_dir ( provided_libs_path) ?) ;
178- }
156+ // Collect the names of all libraries that are available on Android
157+ for provided_libs_path in provided_libs_paths {
158+ included_libs. extend ( xcommon:: llvm:: find_libs_in_dir ( provided_libs_path) ?) ;
159+ }
179160
180- // libc++_shared is bundled with the NDK but not available on-device
181- included_libs. remove ( OsStr :: new ( "libc++_shared.so" ) ) ;
161+ // libc++_shared is bundled with the NDK but not available on-device
162+ included_libs. remove ( OsStr :: new ( "libc++_shared.so" ) ) ;
182163
183- let mut needs_cpp_shared = false ;
164+ let mut needs_cpp_shared = false ;
184165
185- for lib in explicit_libs {
186- apk . add_lib ( target. android_abi ( ) , & lib) ? ;
166+ for lib in explicit_libs {
167+ libraries . push ( ( target. android_abi ( ) , lib. clone ( ) ) ) ;
187168
188- let ( extra_libs, cpp_shared) = xcommon:: llvm:: list_needed_libs_recursively (
169+ let ( extra_libs, cpp_shared) = xcommon:: llvm:: list_needed_libs_recursively (
189170 & lib,
190171 & search_paths,
191172 & included_libs,
@@ -198,18 +179,41 @@ pub fn build(env: &BuildEnv) -> Result<()> {
198179 search_paths
199180 )
200181 } ) ?;
201- needs_cpp_shared |= cpp_shared;
202- for lib in & extra_libs {
203- apk. add_lib ( target. android_abi ( ) , lib) ?;
204- }
205- }
206- if needs_cpp_shared {
207- let cpp_shared = ndk_sysroot_libs. join ( "libc++_shared.so" ) ;
208- apk. add_lib ( target. android_abi ( ) , & cpp_shared) ?;
209- }
182+ needs_cpp_shared |= cpp_shared;
183+ for lib in extra_libs {
184+ libraries. push ( ( target. android_abi ( ) , lib) ) ;
185+ }
186+ }
187+ if needs_cpp_shared {
188+ let cpp_shared = ndk_sysroot_libs. join ( "libc++_shared.so" ) ;
189+ libraries. push ( ( target. android_abi ( ) , cpp_shared) ) ;
190+ }
191+ }
192+
193+ if env. config ( ) . android ( ) . gradle {
194+ crate :: gradle:: build ( env, libraries, & out) ?;
195+ runner. end_verbose_task ( ) ;
196+ return Ok ( ( ) ) ;
197+ } else {
198+ let mut apk = Apk :: new (
199+ out,
200+ env. config ( ) . android ( ) . manifest . clone ( ) ,
201+ env. target ( ) . opt ( ) != Opt :: Debug ,
202+ ) ?;
203+ apk. add_res ( env. icon ( ) , & env. android_jar ( ) ) ?;
204+
205+ for asset in & env. config ( ) . android ( ) . assets {
206+ let path = env. cargo ( ) . package_root ( ) . join ( asset. path ( ) ) ;
207+
208+ if !asset. optional ( ) || path. exists ( ) {
209+ apk. add_asset ( & path, asset. alignment ( ) . to_zip_file_options ( ) ) ?
210210 }
211211 }
212212
213+ for ( target, lib) in libraries {
214+ apk. add_lib ( target, & lib) ?;
215+ }
216+
213217 apk. finish ( env. target ( ) . signer ( ) . cloned ( ) ) ?;
214218 }
215219 }
0 commit comments