Subversion Repositories DevTools

Rev

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