Subversion Repositories DevTools

Rev

Rev 6463 | Rev 7470 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4937 dpurdie 1
########################################################################
2
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
3
#
4
# Module name   : androidBuilder.pl
5
# Module type   : Makefile system
6
# Compiler(s)   : Perl
7
# Environment(s): jats
8
#
9
# Description   : This program is invoked by the JATS Makefile System
10
#                 to 'build' an Android project from an AndroidStudio based
11
#                 Android project. It does this by:
12
#                   Creating a build.xml file from the Eclispe files
13
#                   Injecting properties into the build
14
#                       Create gradle.properties (Must not be version controlled)
15
#                       Create local.properties (Must not be version controlled)
16
#                   Insert external dependencies
17
#                       Jar files
18
#                       Aar files
19
#                       JNI Libraries
20
#                   Invoking 'gradle' to perform the build 
21
#
22
#                 This process requires external tool - delivered in packages
23
#                 These are:
24
#                   gradle      - Provides the core of gradle
25
#                   androidSdk  - From package rather than installed
26
#                                 This provides flexability when a new Sdk
27
#                                 is required
28
#
29
# Usage:        The utility is invoked in a controlled manner from a Jats
30
#               makefile. The call is generated by the Android Toolset
31
#               Arguments:
32
#                -verbose                   - Increase debugging
33
#                -verbose=n                 - Increase debugging
34
#                -f=manifestFile.xml        - project Manifest file
35
#                -i=path                    - Path to the interface directory
36
#                -t=[P|D]"                  - Build Type. Production or Debug
37
#                -pn=PackageName            - Package Name
38
#                -pv=PackageVersion         - Package Version
39
#                -clean                     - Will clean the build
40
#                -populate                  - Test Env and Populate 'libs'
5412 dpurdie 41
#                -autotest                  - Run Unit Tests
5444 dpurdie 42
#                -hasTests                  - Build unit tests too    
4937 dpurdie 43
#               Aguments that can be provided by the user
44
#                -Jar=name                  - Name of a Jar to include
45
#                -Aar=name                  - Name of an Aar to include
46
#                -lname                     - Name of a Jats library to include
47
#                -Lname                     - Name of a 3rd party library to include
48
#
49
# Note: This function may be provided by several packages, 
50
#       thus the interface must not change - this include the name of 
51
#       this file. See the AndroidBuilder package too.
52
#
53
#
54
#......................................................................#
55
 
56
require 5.008_002;
57
use strict;
58
use warnings;
59
 
60
use Getopt::Long qw(:config pass_through);
61
use File::Path;
62
 
63
use JatsError;
64
use JatsSystem;
65
use JatsEnv;
66
use FileUtils;
67
use JatsProperties;
68
use JatsVersionUtils;
69
use ReadBuildConfig;
70
use JatsCopy;
71
use ArrayHashUtils;
72
 
73
#
74
#   Globals
75
#   Command line arguments
76
#
77
my $opt_verbose = $ENV{GBE_VERBOSE};
78
my $opt_buildFile;
79
my $opt_interface;
80
my $opt_gbetype = 'P';
6351 dpurdie 81
my @opt_gbetypes;
4937 dpurdie 82
my $opt_clean;
83
my $opt_pkgname;
84
my $opt_pkgversion;
85
my $opt_platform;
86
my $opt_populate;
6351 dpurdie 87
my $opt_populateDebug;
88
my $opt_populateProd;
5412 dpurdie 89
my $opt_autotest;
5444 dpurdie 90
my $opt_hastests;
4937 dpurdie 91
my @opt_jlibs;                  # List of Jats Libraries
92
my @opt_elibs;                  # List of 3rd party libraries
93
my @opt_jars;                   # List of JARs
94
my @opt_aars;                   # List of AARs
95
 
96
#
97
#   Configuration
98
#   Map JATS platforms to Shared library targets
6455 dpurdie 99
#       The key is a JATS name for the target
100
#       The value is the subdir that android will expect to find the files in
4937 dpurdie 101
#
102
my %SharedLibMap = (
6455 dpurdie 103
    'ANDROIDARM'    => 'armeabi',
6463 dpurdie 104
    'ANDROIDARMV7'  => 'armeabi-v7a',
4937 dpurdie 105
    'ANDROIDMIPS'   => 'mips',
106
    'ANDROIDX86'    => 'x86',
6444 dpurdie 107
 
108
    'ANDROIDARM64'  => 'arm64-v8a',
109
    'ANDROIDMIPS64' => 'mips64',
110
    'ANDROIDX86_64' => 'x86_64',
4937 dpurdie 111
    );
112
 
113
our $GBE_HOSTMACH;              # Sanity Test of machine type
114
our $GBE_MAKE_TARGET;           # Current build target
115
 
116
my $androidJars;                # Root of injected JARs and AARs
117
my $androidJniBase;             # Root of injected JNI files
118
my $androidJniProd;             # Root of injected JNI files - Prod
119
my $androidJniDebug;            # Root of injected JNI files - Debug
120
my $androidBuildSuffix = '';    # Prefix build commands
121
 
122
#-------------------------------------------------------------------------------
123
# Function        : Main Entry Point 
124
#
125
# Description     : Main entry to this program
126
#
127
# Inputs          : @ARGV           - Array of command line arguments
128
#                                     See file header
129
#
130
# Returns         : 0               - No Error
131
#                   1               - Error encountered    
132
#
133
InitFileUtils();
134
ErrorConfig( 'name'    => 'ANDROIDBUILDER',
135
             'verbose' => $opt_verbose);
136
$opt_verbose = $::ScmVerbose;               # Get the calculated verbosity level
137
 
138
#
139
#   Install local signal handlers to process GetOptions messages
140
#
141
local $SIG{__WARN__} = sub { ReportError('AndroidBuilder.' . "@_"); };
142
local $SIG{__DIE__} = sub { ReportError('AndroidBuilder.' . "@_"); };
143
my $result = GetOptions (
144
                "verbose:+"     => \$opt_verbose,       # flag
145
                "f=s"           => \$opt_buildFile,     # string
146
                "i=s"           => \$opt_interface,     # Interface directory
6351 dpurdie 147
                "t=s"           => \@opt_gbetypes,      # string
4937 dpurdie 148
                "pn=s"          => \$opt_pkgname,       # string
149
                "pv=s"          => \$opt_pkgversion,    # string
150
                "pf=s"          => \$opt_platform,      # string
151
                "clean"         => \$opt_clean,         # flag
152
                "populate"      => \$opt_populate,      # flag
5412 dpurdie 153
                "autotest"      => \$opt_autotest,      # flag
5444 dpurdie 154
                "hastests"      => \$opt_hastests,      # flag
4937 dpurdie 155
                "Jar=s"         => \@opt_jars,
156
                "Aar=s"         => \@opt_aars,
157
                );
158
 
159
#
160
#   Restore signal handlers and report parse errors
161
#
162
$SIG{__WARN__} = 'DEFAULT';
163
$SIG{__DIE__} = 'DEFAULT';
164
Error('AndroidBuilder. Invalid call options detected') if (!$result);
165
 
166
#
167
#   Process remaining arguments
168
#   Only --Lname and --lname are valid
169
#
170
foreach my $arg (@ARGV) {
171
    if ($arg =~ m~^[-]{1,2}l(.*)~) {
172
        push @opt_jlibs, $1;
173
    } elsif ($arg =~ m~^[-]{1,2}L(.*)~) {
174
        push @opt_elibs, $1;
175
    } else {
176
        ReportError("Invalid option: $arg");
177
    }
178
}
6351 dpurdie 179
 
4937 dpurdie 180
ErrorDoExit();
181
 
182
#
183
#   Sanity Test
184
#
185
ReportError ("Gradle build file not specified") unless ( defined $opt_buildFile); 
186
ReportError ("Gradle build file not found: $opt_buildFile") unless ( -f $opt_buildFile);
187
 
188
ReportError ("Interface directory not specified") unless ( defined $opt_interface);
189
ReportError ("Interface directory not found: $opt_interface") unless ( -d $opt_interface);
190
 
191
ReportError ("Package Name not specified") unless ( defined $opt_pkgname); 
192
ReportError ("Package Version not specified") unless ( defined $opt_pkgversion); 
193
 
194
EnvImport('GBE_HOSTMACH');
195
ReportError ("AndroidStudioBuilder is only supported under win32","This machine is: ".$::GBE_HOSTMACH ) unless ( $::GBE_HOSTMACH eq 'win32' );
196
ReportError ("Platform not found") unless ( defined $opt_platform );
197
 
198
ErrorDoExit();
199
 
200
#
201
#   Basic setup
202
#
6351 dpurdie 203
#   Handle multiple opt_gbetypes for populate mode
204
#   If we are ony building for Prod, then only populate production artifacts 
205
#   If we are ony building for Debug, then only populate debug artifacts 
206
foreach ( @opt_gbetypes) {
207
    $opt_gbetype = $_;
208
    $opt_populateProd = 1 if ($opt_gbetype eq 'P');
209
    $opt_populateDebug = 1 if ($opt_gbetype eq 'D');
210
}
211
 
4937 dpurdie 212
$androidBuildSuffix = ($opt_gbetype eq 'P') ? 'Release' : 'Debug';
213
 
214
#
215
#   The user provides the root build.gradle file
216
#   There MUST be a settings.gradle in the same directory
217
#       This is a JATS assumption - subject to change
218
#   There will be some other files there too
219
#   Calculate the root of the project
220
#
221
$opt_buildFile = RelPath(AbsPath($opt_buildFile));
222
my $project_root = StripFileExt($opt_buildFile);
223
   $project_root = '.' unless $project_root;
224
my $project_settingsFile = catfile($project_root, 'settings.gradle');
225
 
226
Message ("Project Base:" . Getcwd());
227
Message ("Project Root:" . $project_root);
228
Verbose ("Project Settings file:" . $project_settingsFile);
229
 
230
#
231
#   Directories to store Jar's, Aar's and JNI shared libarares
232
#   are created in the interface directory
233
#
234
$androidJars      = catdir($opt_interface, 'jatsLibs');
235
$androidJniBase   = catdir($opt_interface, 'jatsJni');
236
$androidJniProd   = catdir($androidJniBase, 'Release');
237
$androidJniDebug  = catdir($androidJniBase, 'Debug');
238
 
239
Verbose ("Interface:" . $opt_interface);
240
Verbose ("Android Jars: $androidJars");
241
Verbose ("Android JNI : $androidJniBase");
242
 
243
Error ("Gradle settings file not found: $project_settingsFile") unless ( -f $project_settingsFile);
244
 
245
#
246
#   Essential tool
247
#       gradle     - setup 
248
#                    GRADLE_USER_HOME
249
#                    JAVA_HOME
250
#                    
251
ReadBuildConfig( $opt_interface, $opt_platform, '--NoTest' );
252
 
253
my $gradleTool = getToolInfo('gradle', 'JAVA_VERSION', 'GRADLE_BIN');
254
my $gradleBinDir = catdir($gradleTool->{PKGBASE}, $gradleTool->{TOOLROOT}, $gradleTool->{GRADLE_BIN});
255
 
256
#
257
#   Setup a gradle home
258
#   Its used to cache stuff - create it within the interface directory
259
#
260
my $gradleHomeTarget = CleanPath(FullPath(catdir($opt_interface, 'gradleUserHome')));
261
mkpath($gradleHomeTarget, 0, 0775) 
262
    unless ( -d $gradleHomeTarget);
263
$ENV{GRADLE_USER_HOME} = $gradleHomeTarget;
264
Verbose("GRADLE_USER_HOME:", $ENV{GRADLE_USER_HOME});
265
 
266
#
267
#   Setup the required version of Java for the tool
5289 dpurdie 268
#   Force JAVA_OPTS to set Min/Max Heap
269
#       Use JAVA_OPTS because
270
#           _JAVA_OPTIONS causes ssytem to emit a lot of warnings that _JAVA_OPTIONS is being used
271
#           Use of org.gradle.jvmargs in gradle.properties causes warnins about forking speed
272
#           Fixing the max size will provide consistent builds
273
#           Perhaps one day it will be configured 
4937 dpurdie 274
#
275
my $javaVersion = $gradleTool->{JAVA_VERSION};
276
ReportError ("$javaVersion not defined.", "Building ANDROID requires $javaVersion be installed and correctly configured.") 
277
    unless $ENV{$javaVersion};
278
$ENV{JAVA_HOME}=$ENV{$javaVersion};
5289 dpurdie 279
$ENV{JAVA_OPTS} = '-Xms256m -Xmx1024m';
4937 dpurdie 280
 
281
#
282
#   Essential tool
283
#       androidSdk  - setup path to the android executable
284
#
285
my $androidSdkTool = getToolInfo('androidSdk');
286
my $androidSdk = catdir($androidSdkTool->{PKGBASE}, $androidSdkTool->{TOOLROOT} );
287
Verbose ("Android SDK : $androidSdk");
288
ReportError("Tool Package 'androidSdk' - Invalid SDK Basedir", "Sdk Base: $androidSdk" )
289
    unless -d ($androidSdk);
290
 
291
#   Essential tool
292
#       androidGradleRepo   - A repo of gradle plugings for android
293
#
294
my $androidGradleRepo = getToolInfo('androidGradleRepo');
295
my $gradleMavenRepo = catdir($androidGradleRepo->{PKGBASE}, $androidGradleRepo->{TOOLROOT});
296
Verbose ("Maven Repo. Gradle support for android : $gradleMavenRepo");
297
 
298
ErrorDoExit();
299
 
300
#
301
#   Create a gradle file with JATS provided version information
302
#   and paths for use within the gradle build.
303
#
304
#   Always do this as the 'clean' will need them
305
#
306
createGradleFiles($opt_clean);
307
 
308
#
309
#   Clean out any build artifacts
310
#
311
if ($opt_clean)
312
{
313
    #
314
    #   Invoke GRADLE on the build script - if present
315
    #
316
    Message ("Clean the existing build");
317
    runGradle ('clean');
318
    deleteGeneratedFiles();
319
    exit 0;
320
}
321
 
322
#
323
#   If we are only populating the build then we 
324
#   need to inject dependencies.
325
#
326
if ($opt_populate)
327
{
328
    deleteInjectedFiles();
329
    injectDependencies();
330
 
331
    Verbose ("Populate complete");
332
    exit 0;
333
}
334
 
335
#
336
#   Build the Android project through gradle
337
#
5412 dpurdie 338
my $rv = 0;
339
if ( ! $opt_autotest )
340
{
341
    #
342
    #   Build the project - does not run unit tests
343
    #       assemble all the code
344
    #       assemble code for unit tests -  does not run unit tests 
345
    #
346
    Message ("Build the android project: $androidBuildSuffix");
5444 dpurdie 347
    my @tasks;
348
    push (@tasks, 'assemble'. $androidBuildSuffix); 
349
    push (@tasks, 'assemble' . $androidBuildSuffix . 'UnitTest') if $opt_hastests;
5412 dpurdie 350
    $rv = runGradle('assemble'. $androidBuildSuffix , 'assemble' . $androidBuildSuffix . 'UnitTest');
351
    Error("Cannot build AndroidStudio project") if $rv;
352
}
353
else
354
{
355
    #
356
    #   Run unit tests - does not build the project, although it 
357
    #   will build the unit tests, but these have been buitl before
358
    #   
359
    #   If the gradle run fails, then its because one or more of the unit tests failed
360
    #   This is not a build failure as we want to process the test results and feed
361
    #   them up the chain
362
    #   
363
    #   Post processing MUST detect and report errors
364
    #
365
    Message ("Run Unit Tests within the android project: $androidBuildSuffix");
366
    $rv = runGradle('test'. $androidBuildSuffix);
367
    Message ("Unit Test reports: $rv");
368
}
4937 dpurdie 369
exit(0);
370
 
371
#-------------------------------------------------------------------------------
372
# Function        : runGradle 
373
#
374
# Description     : Run gradle to build the project
375
#                   Generate a command like:
376
#                   PathToGradle/gradle --offline -I SomePath/init.gradle <task> 
377
#
378
#                   Use an init-script to inject a sanity test into the build
379
#                   Ensure that the user is using our version numbers.
380
#
381
# Inputs          : task        - Task to run
382
#
383
# Returns         : Returns the error code of the build
384
#
385
sub runGradle
386
{
5412 dpurdie 387
    my (@tasks) = @_;
388
    Verbose ("runGradle: @tasks");
4937 dpurdie 389
 
390
    #   The Windows batch file can run in debug mode
391
    #   Make sure that it doesn't by default
392
    $ENV{DEBUG} = "" unless $opt_verbose;
393
 
394
    my $gradleProg = catdir($gradleBinDir, 'gradle');
395
    Verbose ("GradleProg: $gradleProg");
396
 
397
    #
398
    #   Locate the 'init.gradle' script
399
    #   Its co-located with this script
400
    #
401
    my $initScript = catdir(StripFileExt(__FILE__), 'init.gradle');
402
    Verbose ("Gradle Init Script: $initScript");
403
 
404
    #
405
    #   Build up the arg list
406
    #
407
    my @gradleArgs;
408
    push (@gradleArgs, '--offline');
7056 dpurdie 409
    push (@gradleArgs, '--no-daemon');
4937 dpurdie 410
#    push (@gradleArgs, '--info');
411
#    push (@gradleArgs, '--debug');
5307 dpurdie 412
#    push (@gradleArgs, '--stacktrace');
4937 dpurdie 413
    push (@gradleArgs, '--info') if $opt_verbose;
414
    push (@gradleArgs, '--debug') if ($opt_verbose > 2);
5307 dpurdie 415
    push (@gradleArgs, '--stacktrace') if ($opt_verbose > 3);
5412 dpurdie 416
    push (@gradleArgs, '-I', $initScript) unless ($tasks[0] =~ m/clean/); 
5307 dpurdie 417
    push (@gradleArgs, '-p', $project_root);
4937 dpurdie 418
 
5412 dpurdie 419
    my $rv = System('--NoShell', '--NoExit', $gradleProg, @gradleArgs, @tasks);
4937 dpurdie 420
    return $rv;
421
}
422
 
423
#-------------------------------------------------------------------------------
424
# Function        : createGradleFiles 
425
#
426
# Description     : Calculate Version information
427
#                       gradle.properies
428
#                       local.properties
429
#
430
# Inputs          : quiet           - No output 
431
#
432
# Returns         : Nothing
433
#
434
sub createGradleFiles
435
{
436
    my ($quiet) = @_;
437
 
438
    #
439
    #   Generate Package Versioning information   
440
    #       Need a text string and a number
441
    #       Generate the 'number' from the version number
442
    #
443
    my $version_text;
444
    my $version_num;
445
 
446
    $version_text = $opt_pkgversion;
447
    my ($major, $minor, $patch, $build )= SplitVersion($opt_pkgversion);
448
    foreach my $item ($major, $minor, $patch, $build)
449
    {
450
        Error("Package version has invalid form. It contains non-numeric parts", $item)
451
            unless ( $item =~ m~^\d+$~);
452
    }
453
    $version_num = ($major << 24) + ($minor << 16) + ($patch << 8) + $build;
454
 
455
    Message ("Project Version Txt:" . $version_text) unless $quiet;
456
    Message ("Project Version Num:" . $version_num) unless $quiet;
457
 
458
    #
459
    #   Create the gradle.properties file
460
    #       It needs to be in the projects root directory
461
    #
462
    my $gradleProperies = catfile($project_root,'gradle.properties');
463
    Message ("Create gradle.properties file: " . $gradleProperies) unless $quiet;
464
 
465
    my $data = JatsProperties::New();
466
 
467
    $data->setProperty('GBE_VERSION_NAME' , $version_text);
468
    $data->setProperty('GBE_VERSION_CODE' , $version_num);
469
 
470
    $data->setProperty('GBE_JARLIBS'        , NicePath($androidJars));
471
    $data->setProperty('GBE_JNI_RELEASE'    , NicePath($androidJniProd));
472
    $data->setProperty('GBE_JNI_DEBUG'      , NicePath($androidJniDebug));
473
    $data->setProperty('GBE_GRADLE_REPO'    , NicePath($gradleMavenRepo));
474
 
5412 dpurdie 475
    #
476
    #   Create properties for JAVA Stores
477
    #   Name of variable is based on the package name and prject suffix
478
    #       Forced to uppercase
479
    #       '-' replaced with '_'
7056 dpurdie 480
    #   Locate 'jar' dir and save path as GBE_REPO_<pkgName>
481
    #   Locate 'mavenRepository' and save path as GBE_MVN_<pkgName>
5412 dpurdie 482
    #
483
    foreach my $pkg (getPackageList())
484
    {
485
        my $base = $pkg->getBase(3);
486
        if ($base)
487
        {
488
            my $jarDir = catdir($base, 'jar');
489
            if (-d $jarDir )
490
            {
491
                $data->setProperty( $pkg->getUnifiedName('GBE_REPO_') , NicePath($jarDir));
492
            }
7056 dpurdie 493
 
494
            my $mvnDir = catdir($base, 'mavenRepository');
495
            if (-d $mvnDir ) {
496
                $data->setProperty( $pkg->getUnifiedName('GBE_MVN_') , NicePath($mvnDir));
497
            }
5412 dpurdie 498
        }
499
    }
500
 
4937 dpurdie 501
    $data->store( $gradleProperies );
502
 
503
    #
504
    #   Create the local.properties file
505
    #       It needs to be in the projects root directory
506
    #
507
    #   May be able to do without this file - iff we set ANDROID_HOME
508
    #
509
    my $localProperies = catfile($project_root,'local.properties');
510
    Message ("Create local.properties file: " . $localProperies) unless $quiet;
511
 
512
    $data = JatsProperties::New();
513
    $data->setProperty('sdk.dir' , NicePath($androidSdk));
514
    $data->store( $localProperies );
515
}
516
 
517
#-------------------------------------------------------------------------------
518
# Function        : injectDependencies 
519
#
520
# Description     : Inject dependencies
521
#
522
#                   The android build can make use of files in a specific directory
523
#                   Place Jar and Aar files in a specific directory under the root of the project
524
#                   Use a directory called jatsLibs
525
#                   There are two types of files that can be placed in that directory
526
#                   These appear to be:
527
#                       1) .jar files
528
#                       2) .aar files
529
#
530
#                   NDK files will be process automatically by the builder, once the build is made
531
#                   aware of the location. We are not using the AndroidStudio default location
532
#                   Place them into jatsJni within the project root
533
#                       1) Shared libraries provided by NDK components
534
#
535
#                   Need to keep the production and debug JNI files seperate
536
#
537
#                   The gradle dependency processing needs both production and
538
#                   debug dependencies to be present at all times
539
#                   
540
#                   Create three areas:
541
#                       jatsLibs        - Prod and Debug Jars and Ars
542
#                       jatsJniDebug    - Debug JNI files
543
#                       jatsJniProd     - Production JNI files
544
#
545
# Inputs          : 
546
#
547
# Returns         : 
548
#
549
sub injectDependencies
550
{
551
    my @jlist;                  # List of JARs from default directories
552
    my @jpathlist;              # List of JARs from named directories
553
    my @alist;                  # List of AARs from default directories
554
    my @apathlist;              # List of AARs from named directories
555
    my @libListProd;            # List of production libraries
556
    my @libListDebug;           # List of debug libraries
557
    my @platformParts;          # Platforms Parts
558
 
4990 dpurdie 559
    my @jarSearch;              # Search paths - diagnostic display
560
    my @aarSearch;
561
    my @libSearch;
4937 dpurdie 562
 
4990 dpurdie 563
 
4937 dpurdie 564
    #
565
    #   Only if we need to do something
566
    #
567
    return unless (@opt_jars || @opt_aars || @opt_elibs || @opt_jlibs);
568
 
569
    #
570
    #   Determine the list of platformm parts
571
    #   This is where 'lib' files will be found
572
    #
573
    @platformParts = getPlatformParts();
574
    Verbose("Platform Parts", @platformParts);
575
 
576
    #
577
    #   Create search entries suitable for the CopyDir
578
    #   We will delete entries as the files are copied
579
    #   Allow for:
580
    #       jar/aar files to have a .jar /.aar suffix (optional)
581
    #       jar/aar files to have path specified with a package
582
    #
583
    #   Split into two lists ( per type ): 
584
    #       Those with a path and those without
585
    #
586
    foreach my $item ( @opt_jars) {
587
        $item =~ s~\.jar~~i;
588
        if ($item =~ m~/~) {
589
            UniquePush \@jpathlist, $item;
590
        } else {
591
            UniquePush \@jlist, $item;
592
        }
593
    }
594
 
595
    foreach my $item ( @opt_aars) {
596
        $item =~ s~\.aar~~i;
597
        if ($item =~ m~/~) {
598
            UniquePush \@apathlist, $item;
599
        } else {
600
            UniquePush \@alist, $item;
601
        }
602
    }
603
 
604
    #   Shared libraries
605
    #   Create full names
606
    foreach my $item ( @opt_elibs) {
6351 dpurdie 607
        UniquePush (\@libListDebug, 'lib' . $item . '.so');
608
        UniquePush (\@libListProd,  'lib' . $item . '.so');
4937 dpurdie 609
    }
610
 
611
    foreach my $item ( @opt_jlibs) {
6351 dpurdie 612
        UniquePush (\@libListDebug, 'lib' . $item . 'D.so') if $opt_populateDebug;
613
        UniquePush (\@libListProd , 'lib' . $item . 'P.so') if $opt_populateProd;
4937 dpurdie 614
    }
615
 
616
    #
617
    #   Where does it go
618
    #       JARs/AARs - ROOT/jatsLibs
619
    #       LIBS      - ROOT/jatsJni
620
    #
621
    #   Scan all external packages, and the interface directory
622
    #       Transfer in the required file types
623
    #
624
    my @pkg_paths = getPackagePaths("--Interface=$opt_interface");
625
    foreach my $pkg ( @pkg_paths)
626
    {
627
        #
628
        #   Copy in all JAR files found in dependent packages
629
        #   Need to allow for Jars that have a P/D suffix as well as those that don't
630
        #
631
        my $jarDir = catdir($pkg,'jar');
4990 dpurdie 632
        push @jarSearch, $jarDir;
4937 dpurdie 633
        if (-d $jarDir && @jlist)
634
        {
635
            Verbose("Jar Dir Found found", $jarDir);
636
            Message ("Copy in: $jarDir");
637
 
638
            #
639
            #   Create a matchlist from the JAR list
640
            #   Create a regular expresssion to find a suitable file
641
            #
642
            my @mlist;
643
            foreach  ( @jlist) {
644
                push @mlist, $_ . '.jar|' . $_ . 'P.jar|'. $_ . 'D.jar';
645
            }
646
            CopyDir ( $jarDir, $androidJars,
647
                        'MatchRE' => \@mlist,
648
                        'Log' => $opt_verbose + 1,
649
                        'SymlinkFiles' => 1,
650
                        'Examine' => sub 
651
                            {
652
                                my ($opt) = @_;
653
                                my $baseName = $opt->{file};
654
                                $baseName =~ s~\.jar~~;
655
                                $baseName =~ s~[PD]$~~;
656
                                ArrayDelete \@jlist, $baseName;
657
                                return 1;
658
                            },
659
                    );
660
        }
661
 
662
        #
663
        #   Copy in JARs specified by a full pathname
664
        #   Need to allow for Jars that have a P/D suffix as well as those that don't
665
        #
666
        my @jpathlistBase = @jpathlist;
667
        foreach my $file (@jpathlistBase) 
668
        {
669
            foreach my $suffix ( '', 'P' ,'D')
670
            {
671
                my $jarFile = catdir($pkg, $file . $suffix . '.jar');
4990 dpurdie 672
                push @jarSearch, $jarFile;
4937 dpurdie 673
                if (-f $jarFile)
674
                {
675
                    Verbose("Jar File Found found", $jarDir);
676
                    Message ("Copy in: $jarFile");
677
                    CopyFile ( $jarFile, $androidJars,
678
                                'Log' => $opt_verbose + 1,
679
                                'SymlinkFiles' => 1,
680
                             );
681
                    ArrayDelete \@jpathlist, $file;
682
                }
683
            }
684
        }
685
 
686
        #
687
        #   Copy in AAR files found in dependent packages
688
        #   Need to allow for both AAR files with a -debug/-release suffix 
689
        #   as well as those without
690
        #
691
        foreach my $part (@platformParts)
692
        {
693
            my $aarDir = catdir($pkg,'lib/' . $part);
4990 dpurdie 694
            push @aarSearch, $aarDir;
4937 dpurdie 695
            if (-d $aarDir && @alist)
696
            {
697
                Verbose("Library Dir Found found", $aarDir);
698
                Message ("Copy in: $aarDir");
699
 
700
                #
701
                #   Create a matchlist from the AAR list
702
                #   Create a regular expresssion to find a suitable file
703
                #
704
                my @mlist;
705
                foreach  ( @alist) {
706
                    push @mlist, $_ . '.aar|' . $_ . '-debug.aar|' . $_ . '-release.aar';
707
                }
708
 
709
                CopyDir ( $aarDir, $androidJars,
710
                            'MatchRE' => \@mlist,
711
                            'Log' => $opt_verbose + 1,
712
                            'SymlinkFiles' => 1,
713
                            'Examine' => sub 
714
                                {
715
                                    my ($opt) = @_;
716
                                    my $baseName = $opt->{file};
717
                                    $baseName =~ s~\.aar$~~;
718
                                    $baseName =~ s~-release$~~;
719
                                    $baseName =~ s~-debug$~~;
720
                                    ArrayDelete \@alist, $baseName;
721
                                    return 1;
722
                                },
723
                            );
724
            }
725
        }
726
 
727
 
728
        #
729
        #   Copy in AAR files specified by a full pathname
730
        #   Need to allow for both AAR files with a -debug/-release suffix 
731
        #   as well as those without
732
        #
733
        my @apathlistBase = @apathlist;
734
        foreach my $file (@apathlistBase) 
735
        {
736
            foreach my $suffix ( '', '-release', '-debug')
737
            {
738
                my $aarFile = catdir($pkg, $file . $suffix . '.aar');
4990 dpurdie 739
                push @aarSearch, $aarFile;
4937 dpurdie 740
                if (-f $aarFile)
741
                {
742
                    Verbose("Aar File Found found", $aarFile);
743
                    Message ("Copy in: $aarFile");
744
                    CopyFile ( $aarFile, $androidJars,
745
                                'Log' => $opt_verbose + 1,
746
                                'SymlinkFiles' => 1,
747
                             );
748
                    ArrayDelete \@apathlist, $file;
749
                }
750
            }
751
        }
752
 
753
        #
754
        #   Build up the Shared Library structure as used by JNI
755
        #   Note: Only support current JATS format
756
        #   Copy in .so files and in to process massage the pathname so that
757
        #   it confirms to that expected by the Android Project
758
        #
759
        my $libDir = catdir($pkg, 'lib');
4990 dpurdie 760
        push @libSearch, $libDir;
4937 dpurdie 761
        if (-d $libDir && @libListProd)
762
        {
763
            Verbose("Lib Dir Found found", $libDir);
764
            Message ("Copy in: $libDir");
765
            CopyDir ( $libDir, $androidJniProd,
766
                        'Match' => \@libListProd,
767
                        'Log' => $opt_verbose + 1,
768
                        'SymlinkFiles' => 1,
769
                        'Examine' => sub 
770
                            { 
771
                                my ($opt) = @_;
772
                                foreach my $platform ( keys %SharedLibMap ) {
773
                                    my $replace = $SharedLibMap{$platform};
774
                                    if ($opt->{'target'} =~ s~/$platform/~/$replace/~)
775
                                    {
776
                                        ArrayDelete \@libListProd, $opt->{file};
777
                                        return 1;
778
                                    }
779
                                }
780
                                return 0;
781
                            },
782
                    );
783
        }
784
 
785
        if (-d $libDir && @libListDebug)
786
        {
787
            Verbose("Lib Dir Found found", $libDir);
788
            Message ("Copy in: $libDir");
789
            CopyDir ( $libDir, $androidJniDebug,
790
                        'Match' => \@libListDebug,
791
                        'Log' => $opt_verbose + 1,
792
                        'SymlinkFiles' => 1,
793
                        'Examine' => sub 
794
                            { 
795
                                my ($opt) = @_;
796
                                foreach my $platform ( keys %SharedLibMap ) {
797
                                    my $replace = $SharedLibMap{$platform};
798
                                    if ($opt->{'target'} =~ s~/$platform/~/$replace/~)
799
                                    {
800
                                        ArrayDelete \@libListDebug, $opt->{file};
801
                                        return 1;
802
                                    }
803
                                }
804
                                return 0;
805
                            },
806
                    );
807
        }
808
 
809
    }
810
 
811
    #
812
    #   Report files that could not be located. They were deleted from the lists
813
    #   as they were processed
814
    #
4990 dpurdie 815
    if (@jlist || @jpathlist || @alist || @apathlist ||  @libListProd || @libListDebug )
4937 dpurdie 816
    {
4990 dpurdie 817
        ReportError("External dependencies not found:", @jlist , @jpathlist , @alist , @apathlist ,  @libListProd , @libListDebug);
818
        if (@jlist || @jpathlist)
819
        {
820
            ReportError("Jar Search Path", @jarSearch);
821
        }
822
 
823
        if (@alist || @apathlist)
824
        {
825
            ReportError("Aar Search Path", @aarSearch);
826
        }
827
 
828
        if ( @libListProd || @libListDebug)
829
        {
830
            ReportError("Lib Search Path", @libSearch);
831
        }
832
    ErrorDoExit();
4937 dpurdie 833
    }
834
}
835
 
836
#-------------------------------------------------------------------------------
837
# Function        : deleteGeneratedFiles 
838
#
839
# Description     : Delete files that we generate
840
#
841
# Inputs          : 
842
#
843
# Returns         : 
844
#
845
sub deleteGeneratedFiles
846
{
847
    #
848
    #   Delete files that we will create
849
    #
850
    my @deleteList = qw(local.properties gradle.properties);
851
    foreach my $file (@deleteList)
852
    {
853
        Verbose ("Deleting $project_root/$file");
854
        unlink catfile($project_root, $file);
855
    }
856
 
857
}
858
 
859
#-------------------------------------------------------------------------------
860
# Function        : deleteInjectedFiles 
861
#
862
# Description     : Delete files that we inject
863
#
864
# Inputs          : 
865
#
866
# Returns         : 
867
#
868
sub deleteInjectedFiles
869
{
870
    #
871
    #   Remove the jatsJars and JatsJni directories
872
    #   These are created by this tool
873
    #
874
    Verbose("RmDirTree($androidJars)");
875
    RmDirTree($androidJars);
876
 
877
    Verbose("RmDirTree($androidJniBase)");
878
    RmDirTree($androidJniBase);
879
}
880
 
881
 
882
#-------------------------------------------------------------------------------
883
# Function        : NicePath 
884
#
885
# Description     : Process a path and return one that is
886
#                       An absolute Path
887
#                       Uses '/'
888
#
889
# Inputs          : path            - Path to process
890
#
891
# Returns         : A Nice version of path
892
#
893
sub NicePath
894
{
895
    my ($path) = @_;
896
    $path = FullPath($path);
897
    $path =~ s~\\~/~g;
898
    $path = CleanPath($path);
899
    return $path;
900
}
901