@@ -2,7 +2,7 @@ use crate::cargo::CrateType;
2
2
use crate :: download:: DownloadManager ;
3
3
use crate :: task:: TaskRunner ;
4
4
use crate :: { BuildEnv , Format , Opt , Platform } ;
5
- use anyhow:: { Context , Result } ;
5
+ use anyhow:: { ensure , Context , Result } ;
6
6
use apk:: Apk ;
7
7
use appbundle:: AppBundle ;
8
8
use appimage:: AppImage ;
@@ -71,116 +71,97 @@ pub fn build(env: &BuildEnv) -> Result<()> {
71
71
}
72
72
Platform :: Android => {
73
73
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) ?;
135
+ for entry in entries {
136
+ let entry = entry?;
137
+ let path = entry. path ( ) ;
138
+ if !path. is_dir ( ) && path. extension ( ) == Some ( OsStr :: new ( "so" ) ) {
139
+ explicit_libs. push ( path) ;
140
+ }
91
141
}
92
142
}
93
143
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) ?;
153
- for entry in entries {
154
- let entry = entry?;
155
- let path = entry. path ( ) ;
156
- if !path. is_dir ( ) && path. extension ( ) == Some ( OsStr :: new ( "so" ) ) {
157
- explicit_libs. push ( path) ;
158
- }
159
- }
160
- }
144
+ // Collect the names of libraries provided by the user, and assume these
145
+ // are available for other dependencies to link to, too.
146
+ let mut included_libs = explicit_libs
147
+ . iter ( )
148
+ . map ( |p| p. file_name ( ) . unwrap ( ) . to_owned ( ) )
149
+ . collect :: < HashSet < _ > > ( ) ;
161
150
162
- // Collect the names of libraries provided by the user, and assume these
163
- // are available for other dependencies to link to, too.
164
- let mut included_libs = explicit_libs
165
- . iter ( )
166
- . map ( |p| p. file_name ( ) . unwrap ( ) . to_owned ( ) )
167
- . collect :: < HashSet < _ > > ( ) ;
168
-
169
- // Collect the names of all libraries that are available on Android
170
- for provided_libs_path in provided_libs_paths {
171
- included_libs
172
- . extend ( xcommon:: llvm:: find_libs_in_dir ( provided_libs_path) ?) ;
173
- }
151
+ // Collect the names of all libraries that are available on Android
152
+ for provided_libs_path in provided_libs_paths {
153
+ included_libs. extend ( xcommon:: llvm:: find_libs_in_dir ( provided_libs_path) ?) ;
154
+ }
174
155
175
- // libc++_shared is bundled with the NDK but not available on-device
176
- included_libs. remove ( OsStr :: new ( "libc++_shared.so" ) ) ;
156
+ // libc++_shared is bundled with the NDK but not available on-device
157
+ included_libs. remove ( OsStr :: new ( "libc++_shared.so" ) ) ;
177
158
178
- let mut needs_cpp_shared = false ;
159
+ let mut needs_cpp_shared = false ;
179
160
180
- for lib in explicit_libs {
181
- apk . add_lib ( target. android_abi ( ) , & lib) ? ;
161
+ for lib in explicit_libs {
162
+ libraries . push ( ( target. android_abi ( ) , lib. clone ( ) ) ) ;
182
163
183
- let ( extra_libs, cpp_shared) = xcommon:: llvm:: list_needed_libs_recursively (
164
+ let ( extra_libs, cpp_shared) = xcommon:: llvm:: list_needed_libs_recursively (
184
165
& lib,
185
166
& search_paths,
186
167
& included_libs,
@@ -193,18 +174,41 @@ pub fn build(env: &BuildEnv) -> Result<()> {
193
174
search_paths
194
175
)
195
176
} ) ?;
196
- needs_cpp_shared |= cpp_shared;
197
- for lib in & extra_libs {
198
- apk. add_lib ( target. android_abi ( ) , lib) ?;
199
- }
200
- }
201
- if needs_cpp_shared {
202
- let cpp_shared = ndk_sysroot_libs. join ( "libc++_shared.so" ) ;
203
- apk. add_lib ( target. android_abi ( ) , & cpp_shared) ?;
204
- }
177
+ needs_cpp_shared |= cpp_shared;
178
+ for lib in extra_libs {
179
+ libraries. push ( ( target. android_abi ( ) , lib) ) ;
180
+ }
181
+ }
182
+ if needs_cpp_shared {
183
+ let cpp_shared = ndk_sysroot_libs. join ( "libc++_shared.so" ) ;
184
+ libraries. push ( ( target. android_abi ( ) , cpp_shared) ) ;
185
+ }
186
+ }
187
+
188
+ if env. config ( ) . android ( ) . gradle {
189
+ crate :: gradle:: build ( env, libraries, & out) ?;
190
+ runner. end_verbose_task ( ) ;
191
+ return Ok ( ( ) ) ;
192
+ } else {
193
+ let mut apk = Apk :: new (
194
+ out,
195
+ env. config ( ) . android ( ) . manifest . clone ( ) ,
196
+ env. target ( ) . opt ( ) != Opt :: Debug ,
197
+ ) ?;
198
+ apk. add_res ( env. icon ( ) , & env. android_jar ( ) ) ?;
199
+
200
+ for asset in & env. config ( ) . android ( ) . assets {
201
+ let path = env. cargo ( ) . package_root ( ) . join ( asset. path ( ) ) ;
202
+
203
+ if !asset. optional ( ) || path. exists ( ) {
204
+ apk. add_asset ( & path, asset. alignment ( ) . to_zip_file_options ( ) ) ?
205
205
}
206
206
}
207
207
208
+ for ( target, lib) in libraries {
209
+ apk. add_lib ( target, & lib) ?;
210
+ }
211
+
208
212
apk. finish ( env. target ( ) . signer ( ) . cloned ( ) ) ?;
209
213
}
210
214
}
0 commit comments