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