@@ -68,8 +68,6 @@ public class BuildApk : AndroidTask
6868 [ Required ]
6969 public string [ ] SupportedAbis { get ; set ; }
7070
71- public bool CreatePackagePerAbi { get ; set ; }
72-
7371 public bool EmbedAssemblies { get ; set ; }
7472
7573 public bool BundleAssemblies { get ; set ; }
@@ -121,6 +119,13 @@ public class BuildApk : AndroidTask
121119 [ Output ]
122120 public ITaskItem [ ] OutputFiles { get ; set ; }
123121
122+ [ Output ]
123+ public ITaskItem [ ] OutputApkFiles { get ; set ; }
124+
125+ [ Output ]
126+ public ITaskItem [ ] DSODirectoriesToDelete { get ; set ; }
127+
128+
124129 bool _Debug {
125130 get {
126131 return string . Equals ( Debug , "true" , StringComparison . OrdinalIgnoreCase ) ;
@@ -133,13 +138,13 @@ bool _Debug {
133138 HashSet < string > uncompressedFileExtensions ;
134139
135140 // Do not use trailing / in the path
136- protected virtual string RootPath => "" ;
141+ public string RootPath { get ; set ; } = "" ;
137142
138- protected virtual string DalvikPath => "" ;
143+ public string DalvikPath { get ; set ; } = "" ;
139144
140145 protected virtual CompressionMethod UncompressedMethod => CompressionMethod . Store ;
141146
142- protected virtual void FixupArchive ( ZipArchiveEx zip ) { }
147+ protected virtual void FixupArchive ( ZipArchiveFileListBuilder zip ) { }
143148
144149 List < string > existingEntries = new List < string > ( ) ;
145150
@@ -150,59 +155,8 @@ protected virtual void FixupArchive (ZipArchiveEx zip) { }
150155 void ExecuteWithAbi ( DSOWrapperGenerator . Config dsoWrapperConfig , string [ ] supportedAbis , string apkInputPath , string apkOutputPath , bool debug , bool compress , IDictionary < AndroidTargetArch , Dictionary < string , CompressedAssemblyInfo > > compressedAssembliesInfo , string assemblyStoreApkName )
151156 {
152157 ArchiveFileList files = new ArchiveFileList ( ) ;
153- bool refresh = true ;
154- if ( apkInputPath != null && File . Exists ( apkInputPath ) && ! File . Exists ( apkOutputPath ) ) {
155- Log . LogDebugMessage ( $ "Copying { apkInputPath } to { apkOutputPath } ") ;
156- File . Copy ( apkInputPath , apkOutputPath , overwrite : true ) ;
157- refresh = false ;
158- }
159- using ( var apk = new ZipArchiveEx ( apkOutputPath , File . Exists ( apkOutputPath ) ? FileMode . Open : FileMode . Create ) ) {
160- if ( int . TryParse ( ZipFlushFilesLimit , out int flushFilesLimit ) ) {
161- apk . ZipFlushFilesLimit = flushFilesLimit ;
162- }
163- if ( int . TryParse ( ZipFlushSizeLimit , out int flushSizeLimit ) ) {
164- apk . ZipFlushSizeLimit = flushSizeLimit ;
165- }
166- if ( refresh ) {
167- for ( long i = 0 ; i < apk . Archive . EntryCount ; i ++ ) {
168- ZipEntry e = apk . Archive . ReadEntry ( ( ulong ) i ) ;
169- Log . LogDebugMessage ( $ "Registering item { e . FullName } ") ;
170- existingEntries . Add ( e . FullName ) ;
171- }
172- }
173- if ( apkInputPath != null && File . Exists ( apkInputPath ) && refresh ) {
174- var lastWriteOutput = File . Exists ( apkOutputPath ) ? File . GetLastWriteTimeUtc ( apkOutputPath ) : DateTime . MinValue ;
175- var lastWriteInput = File . GetLastWriteTimeUtc ( apkInputPath ) ;
176- using ( var packaged = new ZipArchiveEx ( apkInputPath , FileMode . Open ) ) {
177- foreach ( var entry in packaged . Archive ) {
178- // NOTE: aapt2 is creating zip entries on Windows such as `assets\subfolder/asset2.txt`
179- var entryName = entry . FullName ;
180- if ( entryName . Contains ( "\\ " ) ) {
181- entryName = entryName . Replace ( '\\ ' , '/' ) ;
182- Log . LogDebugMessage ( $ "Fixing up malformed entry `{ entry . FullName } ` -> `{ entryName } `") ;
183- }
184- Log . LogDebugMessage ( $ "Deregistering item { entryName } ") ;
185- existingEntries . Remove ( entryName ) ;
186- if ( lastWriteInput <= lastWriteOutput ) {
187- Log . LogDebugMessage ( $ "Skipping to next item. { lastWriteInput } <= { lastWriteOutput } .") ;
188- continue ;
189- }
190- if ( apk . Archive . ContainsEntry ( entryName ) ) {
191- ZipEntry e = apk . Archive . ReadEntry ( entryName ) ;
192- // check the CRC values as the ModifiedDate is always 01/01/1980 in the aapt generated file.
193- if ( entry . CRC == e . CRC && entry . CompressedSize == e . CompressedSize ) {
194- Log . LogDebugMessage ( $ "Skipping { entryName } from { apkInputPath } as its up to date.") ;
195- continue ;
196- }
197- }
198- var ms = new MemoryStream ( ) ;
199- entry . Extract ( ms ) ;
200- Log . LogDebugMessage ( $ "Refreshing { entryName } from { apkInputPath } ") ;
201- apk . Archive . AddStream ( ms , entryName , compressionMethod : entry . CompressionMethod ) ;
202- }
203- }
204- }
205- apk . FixupWindowsPathSeparators ( ( a , b ) => Log . LogDebugMessage ( $ "Fixing up malformed entry `{ a } ` -> `{ b } `") ) ;
158+
159+ using ( var apk = new ZipArchiveFileListBuilder ( apkOutputPath , File . Exists ( apkOutputPath ) ? FileMode . Open : FileMode . Create ) ) {
206160
207161 // Add classes.dx
208162 CompressionMethod dexCompressionMethod = GetCompressionMethod ( ".dex" ) ;
@@ -281,7 +235,7 @@ void ExecuteWithAbi (DSOWrapperGenerator.Config dsoWrapperConfig, string [] supp
281235 }
282236 if ( ! forceInclude ) {
283237 foreach ( var pattern in excludePatterns ) {
284- if ( pattern . IsMatch ( path ) ) {
238+ if ( pattern . IsMatch ( path ) ) {
285239 Log . LogDebugMessage ( $ "Ignoring jar entry '{ name } ' from '{ Path . GetFileName ( jarFile ) } '. Filename matched the exclude pattern '{ pattern } '.") ;
286240 exclude = true ;
287241 break ;
@@ -294,38 +248,23 @@ void ExecuteWithAbi (DSOWrapperGenerator.Config dsoWrapperConfig, string [] supp
294248 Log . LogDebugMessage ( "Ignoring jar entry {0} from {1}: the same file already exists in the apk" , name , Path . GetFileName ( jarFile ) ) ;
295249 continue ;
296250 }
297- if ( apk . Archive . Any ( e => e . FullName == path ) ) {
298- Log . LogDebugMessage ( "Failed to add jar entry {0} from {1}: the same file already exists in the apk" , name , Path . GetFileName ( jarFile ) ) ;
299- continue ;
300- }
301- byte [ ] data ;
302- using ( var d = new MemoryStream ( ) ) {
303- jarItem . Extract ( d ) ;
304- data = d . ToArray ( ) ;
305- }
306- Log . LogDebugMessage ( $ "Adding { path } from { jarFile } as the archive file is out of date.") ;
307- apk . AddEntryAndFlush ( data , path ) ;
251+
252+ apk . AddJavaEntryAndFlush ( jarFile , jarItem . FullName , path ) ;
308253 }
309254 }
310255 }
311- // Clean up Removed files.
312- foreach ( var entry in existingEntries ) {
313- // never remove an AndroidManifest. It may be renamed when using aab.
314- if ( string . Compare ( Path . GetFileName ( entry ) , "AndroidManifest.xml" , StringComparison . OrdinalIgnoreCase ) == 0 )
315- continue ;
316- Log . LogDebugMessage ( $ "Removing { entry } as it is not longer required.") ;
317- apk . Archive . DeleteEntry ( entry ) ;
318- }
319- apk . Flush ( ) ;
320256 FixupArchive ( apk ) ;
257+
258+ OutputApkFiles = apk . ApkFiles . ToArray ( ) ;
259+
321260 }
322261 }
323262
324263 public override bool RunTask ( )
325264 {
326265 Aot . TryGetSequencePointsMode ( AndroidSequencePointsMode , out sequencePointsMode ) ;
327266
328- var outputFiles = new List < string > ( ) ;
267+ var outputFiles = new Dictionary < string , string > ( ) ;
329268 uncompressedFileExtensions = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
330269 foreach ( string ? e in UncompressedFileExtensions ? . Split ( new char [ ] { ';' , ',' } , StringSplitOptions . RemoveEmptyEntries ) ?? Array . Empty < string > ( ) ) {
331270 string ? ext = e ? . Trim ( ) ;
@@ -362,25 +301,12 @@ public override bool RunTask ()
362301
363302 DSOWrapperGenerator . Config dsoWrapperConfig = DSOWrapperGenerator . GetConfig ( Log , AndroidBinUtilsDirectory , IntermediateOutputPath ) ;
364303 ExecuteWithAbi ( dsoWrapperConfig , SupportedAbis , ApkInputPath , ApkOutputPath , debug , compress , compressedAssembliesInfo , assemblyStoreApkName : null ) ;
365- outputFiles . Add ( ApkOutputPath ) ;
366- if ( CreatePackagePerAbi && SupportedAbis . Length > 1 ) {
367- var abiArray = new string [ ] { String . Empty } ;
368- foreach ( var abi in SupportedAbis ) {
369- existingEntries . Clear ( ) ;
370- var path = Path . GetDirectoryName ( ApkOutputPath ) ;
371- var apk = Path . GetFileNameWithoutExtension ( ApkOutputPath ) ;
372- abiArray [ 0 ] = abi ;
373- ExecuteWithAbi ( dsoWrapperConfig , abiArray , String . Format ( "{0}-{1}" , ApkInputPath , abi ) ,
374- Path . Combine ( path , String . Format ( "{0}-{1}.apk" , apk , abi ) ) ,
375- debug , compress , compressedAssembliesInfo , assemblyStoreApkName : abi ) ;
376- outputFiles . Add ( Path . Combine ( path , String . Format ( "{0}-{1}.apk" , apk , abi ) ) ) ;
377- }
378- }
304+ outputFiles . Add ( "all" , ApkOutputPath ) ;
379305
380- OutputFiles = outputFiles . Select ( a => new TaskItem ( a ) ) . ToArray ( ) ;
306+ OutputFiles = outputFiles . Select ( a => new TaskItem ( a . Value , new Dictionary < string , string > ( ) { { "Abi" , a . Key } } ) ) . ToArray ( ) ;
381307
382308 Log . LogDebugTaskItems ( " [Output] OutputFiles :" , OutputFiles ) ;
383- DSOWrapperGenerator . CleanUp ( dsoWrapperConfig ) ;
309+ DSODirectoriesToDelete = DSOWrapperGenerator . GetDirectoriesToCleanUp ( dsoWrapperConfig ) . Select ( d => new TaskItem ( d ) ) . ToArray ( ) ;
384310
385311 return ! Log . HasLoggedErrors ;
386312 }
@@ -403,7 +329,7 @@ static Regex FileGlobToRegEx (string fileGlob, RegexOptions options)
403329 return new Regex ( sb . ToString ( ) , options ) ;
404330 }
405331
406- void AddRuntimeConfigBlob ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveEx apk )
332+ void AddRuntimeConfigBlob ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveFileListBuilder apk )
407333 {
408334 // We will place rc.bin in the `lib` directory next to the blob, to make startup slightly faster, as we will find the config file right after we encounter
409335 // our assembly store. Not only that, but also we'll be able to skip scanning the `base.apk` archive when split configs are enabled (which they are in 99%
@@ -420,7 +346,7 @@ void AddRuntimeConfigBlob (DSOWrapperGenerator.Config dsoWrapperConfig, ZipArchi
420346 }
421347 }
422348
423- void AddAssemblies ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveEx apk , bool debug , bool compress , IDictionary < AndroidTargetArch , Dictionary < string , CompressedAssemblyInfo > > compressedAssembliesInfo , string assemblyStoreApkName )
349+ void AddAssemblies ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveFileListBuilder apk , bool debug , bool compress , IDictionary < AndroidTargetArch , Dictionary < string , CompressedAssemblyInfo > > compressedAssembliesInfo , string assemblyStoreApkName )
424350 {
425351 string sourcePath ;
426352 AssemblyCompression . AssemblyData compressedAssembly = null ;
@@ -519,7 +445,7 @@ string CompressAssembly (ITaskItem assembly)
519445 }
520446 }
521447
522- bool AddFileToArchiveIfNewer ( ZipArchiveEx apk , string file , string inArchivePath , CompressionMethod compressionMethod = CompressionMethod . Default )
448+ bool AddFileToArchiveIfNewer ( ZipArchiveFileListBuilder apk , string file , string inArchivePath , CompressionMethod compressionMethod = CompressionMethod . Default )
523449 {
524450 existingEntries . Remove ( inArchivePath . Replace ( Path . DirectorySeparatorChar , '/' ) ) ;
525451 if ( apk . SkipExistingFile ( file , inArchivePath , compressionMethod ) ) {
@@ -531,7 +457,7 @@ bool AddFileToArchiveIfNewer (ZipArchiveEx apk, string file, string inArchivePat
531457 return true ;
532458 }
533459
534- void AddAssemblyConfigEntry ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveEx apk , AndroidTargetArch arch , string assemblyPath , string configFile )
460+ void AddAssemblyConfigEntry ( DSOWrapperGenerator . Config dsoWrapperConfig , ZipArchiveFileListBuilder apk , AndroidTargetArch arch , string assemblyPath , string configFile )
535461 {
536462 string inArchivePath = MonoAndroidHelper . MakeDiscreteAssembliesEntryName ( assemblyPath + Path . GetFileName ( configFile ) ) ;
537463 existingEntries . Remove ( inArchivePath ) ;
@@ -607,7 +533,7 @@ CompressionMethod GetCompressionMethod (string fileName)
607533 return uncompressedFileExtensions . Contains ( Path . GetExtension ( fileName ) ) ? UncompressedMethod : CompressionMethod . Default ;
608534 }
609535
610- void AddNativeLibraryToArchive ( ZipArchiveEx apk , string abi , string filesystemPath , string inArchiveFileName , ITaskItem taskItem )
536+ void AddNativeLibraryToArchive ( ZipArchiveFileListBuilder apk , string abi , string filesystemPath , string inArchiveFileName , ITaskItem taskItem )
611537 {
612538 string archivePath = MakeArchiveLibPath ( abi , inArchiveFileName ) ;
613539 existingEntries . Remove ( archivePath ) ;
@@ -618,10 +544,10 @@ void AddNativeLibraryToArchive (ZipArchiveEx apk, string abi, string filesystemP
618544 }
619545 Log . LogDebugMessage ( $ "Adding native library: { filesystemPath } (APK path: { archivePath } )") ;
620546 ELFHelper . AssertValidLibraryAlignment ( Log , ZipAlignmentPages , filesystemPath , taskItem ) ;
621- apk . AddEntryAndFlush ( archivePath , File . OpenRead ( filesystemPath ) , compressionMethod ) ;
547+ apk . AddFileAndFlush ( filesystemPath , archivePath , compressionMethod ) ;
622548 }
623549
624- void AddRuntimeLibraries ( ZipArchiveEx apk , string [ ] supportedAbis )
550+ void AddRuntimeLibraries ( ZipArchiveFileListBuilder apk , string [ ] supportedAbis )
625551 {
626552 foreach ( var abi in supportedAbis ) {
627553 foreach ( ITaskItem item in ApplicationSharedLibraries ) {
0 commit comments