Subversion Repositories DevTools

Rev

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