Subversion Repositories DevTools

Rev

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