Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
# -*- mode: perl; tabs: 8; indent-width: 4; show-tabs: yes; -*-
2
#
3
# Module name   : GCC
4
# Module type   : Makefile system
5
# Compiler(s)   : ANSI C
6
# Environment(s): GCC
7
#
8
# Description:
9
#       GCC C/C++ toolset
10
#
11
#............................................................................#
12
 
13
use strict;
14
use warnings;
15
 
4034 dpurdie 16
our $ScmPlatform;
17
our $ScmNoToolsTest;
18
 
227 dpurdie 19
##############################################################################
20
#   Configuration information
21
#   Cross reference from CrossCompiler Alias to actual paths
22
#   Structure:
23
#   Hash reference: Array of toolchain information
369 dpurdie 24
#       Mandatory
25
#          ROOT             => Root of compiler
26
#          BASE             => Base for binaries
27
#       Optional
28
#          CC_OPTS          => Additonal Compiler options
4034 dpurdie 29
#          CC_OPTSP         => Production Compiler options
30
#          CC_OPTSD         => Debug Compiler options
369 dpurdie 31
#          UNCONTROLLED     => Boolean to create warning
3967 dpurdie 32
#          PACKAGE_ARCH     => Packageing architecture
33
#          VERSION          => Version reported by GCC
34
#          MACHINE          => Machine reported by GCC
4034 dpurdie 35
#          COMPILER_OPTIONS => Toolset specific compiler initial options
36
#                              This is a comma seperated list
369 dpurdie 37
 
227 dpurdie 38
my %ToolsetConfig = (
39
 
369 dpurdie 40
    'i386-unknown-linux-gnu'    => {
41
        ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/i586-unknown-linux-gnu',
42
        BASE => 'bin/i586-unknown-linux-gnu-',
3967 dpurdie 43
       VERSION      => '4.1.1',
44
       MACHINE      => 'i586-unknown-linux-gnu'
369 dpurdie 45
    },
227 dpurdie 46
 
369 dpurdie 47
    'arm-9tdmi-linux-gnu'       => {
48
        ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/arm-9tdmi-linux-gnu',
3967 dpurdie 49
        BASE => 'bin/arm-9tdmi-linux-gnu-',
50
        VERSION      => '4.1.1',
51
        MACHINE      => 'arm-9tdmi-linux-gnu'
369 dpurdie 52
        },
247 dpurdie 53
 
369 dpurdie 54
    'powerpc-603e-linux-gnu'    => {
55
       ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/powerpc-603e-linux-gnu',
3967 dpurdie 56
       BASE => 'bin/powerpc-603e-linux-gnu-',
57
       VERSION      => '4.1.1',
58
       MACHINE      => 'powerpc-603e-linux-gnu'
369 dpurdie 59
    },
337 dpurdie 60
 
369 dpurdie 61
    'arm-926ejs-linux-gnueabi'  => {
62
       ROOT => '/opt/crosstool/gcc-4.4.3-glibc-2.9/arm-926ejs-linux-gnueabi',
63
       BASE => 'bin/arm-926ejs-linux-gnueabi-',
64
       CC_OPTS => '-Wno-psabi',
3967 dpurdie 65
       VERSION      => '4.4.3',
66
       MACHINE      => 'arm-926ejs-linux-gnueabi'
369 dpurdie 67
    },
68
 
3967 dpurdie 69
    'i686-linux-gnu'    => {
70
       ROOT         => '/usr',
71
       BASE         => 'bin/',
72
       PACKAGE_ARCH => 'i386',
73
       VERSION      => '4.6',
74
       MACHINE      => 'i686-linux-gnu'
75
    },
76
 
227 dpurdie 77
    #
78
    #   Old (not to be used) version of the embedded toolchain
4003 dpurdie 79
    #   This was deprecated in favor of gcc-4.1.1-glibc-2.5
227 dpurdie 80
    #   It is not possible to reproduce old packages using the old compiler
81
    #   This is a known issue
82
    #
369 dpurdie 83
    'i386-unknown-linux-gnu.glibc-2.3.2' => {
84
       ROOT => '/opt/crosstool/gcc-4.1.0-glibc-2.3.2/i386-unknown-linux-gnu',
85
       BASE => 'bin/i386-unknown-linux-gnu-'
86
    },
227 dpurdie 87
 
369 dpurdie 88
    'arm-9tdmi-linux-gnu.glibc-2.3.2' => {
89
       ROOT => '/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu',
90
       BASE => 'bin/arm-9tdmi-linux-gnu-'
91
    },
227 dpurdie 92
 
93
    #
94
    #   Not too sure where this is used
95
    #
369 dpurdie 96
    'armv4l-unknown-linux-gcc' => {
97
       ROOT => '/opt/host/armv4l',
98
       BASE => 'bin/armv4l-unknown-linux-'
99
    },
227 dpurdie 100
 
101
    #
102
    #   The compiler for the current local machine
103
    #
369 dpurdie 104
    'i386-unknown-linux-gcc' => {
105
       ROOT => '/usr',
106
       BASE => 'bin/',
107
       UNCONTROLLED => 1,
3967 dpurdie 108
       PACKAGE_ARCH => 'i386',
369 dpurdie 109
    },
110
);
227 dpurdie 111
 
112
#
113
#   Cross reference from GCCTarget to GBE_MACHTYPE for which it can
114
#   build using the 'native gcc'. This is NOT the preferred mode of operation
115
#   as the compiler is not as controlled as the cross compilers.
116
#
117
my %NativeCompilers = (
118
    'Linux i386'       => 'linux_i386',
119
    );
120
 
121
##############################################################################
122
#   ToolsetInit()
123
#       Runtime initialisation
124
#
125
##############################################################################
126
 
127
ToolsetInit();
128
 
129
sub ToolsetInit
130
{
4034 dpurdie 131
    my( $GCCTarget, $GCCToolchain, $GCCRoot, $GCCBin, $GCCAr, $GCCObjCopy );
132
    my( $GCCFlags,  $GCCFlagsP, $GCCFlagsD );
3967 dpurdie 133
    my( $PkgArch);
4034 dpurdie 134
    my( $arg_alias, $tools_found, $compiler_tool );
227 dpurdie 135
 
136
#.. Toolset configuration
137
#
138
    $::ScmToolsetVersion = "1.0.0";             # our version
139
    $::ScmToolsetGenerate = 0;                  # GEN generate optional
140
    $::ScmToolsetCompilerPath = 1;              # Exports Compiler path to makefile via SCM_COMPILERPATH
271 dpurdie 141
    $::ScmToolsetProgDependancies = 0;          # handle Prog dependancies myself
339 dpurdie 142
    $::ScmToolsetSoName = 1;                    # Shared library supports SoName
227 dpurdie 143
 
144
#.. Standard.rul requirements
145
#
146
    $::s = "asm";
147
    $::o = "o";
148
    $::so = "so";
149
    $::a = "a";
150
    $::exe = "";
151
 
152
#.. Parse arguments
153
#
154
    foreach $_ ( @::ScmToolsetArgs ) {
155
        if (/^--Target=(.*)/) {                 # OS Version
156
            $GCCTarget = "$1";
157
 
158
        } elsif (/^--CrossAlias=(.*)/) {        # CrossCompiler target-alias
159
            $arg_alias = $1;
160
 
4034 dpurdie 161
        } elsif (/^--CompilerTool=(.*)/) {      # CrossCompiler located in package
162
            $compiler_tool = $1;
163
 
227 dpurdie 164
        } else {
165
            Message( "gcc toolset: unknown option $_ -- ignored\n" );
166
        }
167
    }
168
 
169
    foreach $_ ( @::ScmPlatformArgs ) {
170
        if (/^--product=(.*)/) {                # GBE product
171
 
172
        } else {
173
            Message( "gcc toolset: unknown platform argument $_ -- ignored\n" );
174
        }
175
    }
176
 
177
    Error ("TOOLSET/gcc - Target undefined" )
178
        unless ($GCCTarget);
179
 
4034 dpurdie 180
    #
181
    #   If the toolset is not required, then do not process any futher
182
    #   We may not find the compiler
183
    #
184
    return
185
        if ($ScmNoToolsTest);
186
 
227 dpurdie 187
#.. Cross compile support
4034 dpurdie 188
#   Compiler provided in package, rather than install on machine
227 dpurdie 189
#
4034 dpurdie 190
if ( $compiler_tool  )
191
{
192
    #
193
    #   The GCC toolset will handle a compiler provided within a package
194
    #   Initial requirement was for ANDROID NDKs where the compiler is
195
    #   a part of the NDK and will change.
196
    #
197
    #   Compilers in packages will have a file in gbe/COMPILERS/<compiler_tool>
198
    #   that contains data specifically designed for this toolset
199
    #
200
    Verbose("Locate compiler in package: $compiler_tool");
201
    my @toolList;
202
    my $toolPath;
203
    my $toolPkg;
204
    for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} })
205
    {
206
        my $tpath = join('/', $entry->{ROOT}, 'gbe', 'COMPILERS' , $compiler_tool);
207
        if ( -f $tpath  )
208
        {
209
            push @toolList, $entry->{NAME};
210
            $toolPath = $tpath;
211
            $toolPkg = $entry;
212
        }
213
    }
214
    Error ("Multiple packages provide required compiler:", @toolList)
215
        if ( scalar(@toolList) > 1 );
216
    Error ("Required compiler not found in any package", "Compiler: $compiler_tool")
217
        unless ( scalar(@toolList) == 1 );
218
 
219
    #
220
    #   Process the compiler info file
221
    #   Rip out the data and create a hash of item/values
222
    #   File format:
223
    #       '#' is a line comment
224
    #       item=value
225
    #
226
    my %data;
227
    open (my $DATA, '<', $toolPath ) || Error("Cannot open compiler datafile. $!", "File: $toolPath");
228
    while ( <$DATA> )
229
    {
230
        $_ =~ s~\s+$~~;
231
        next if ( m~^#~ );
232
        m~(.*?)\s*=\s*(.*)~;
233
        $data{$1} = $2;
234
    }
235
    close $DATA;
236
 
237
    #
238
    #   Force this compilers data into the ToolsetConfig hash
239
    #
240
    $arg_alias = $compiler_tool;
241
    %ToolsetConfig = ();
242
 
243
    $ToolsetConfig{$arg_alias}{ROOT} = join('/', $toolPkg->{ROOT}, $data{ROOT} );
244
    $ToolsetConfig{$arg_alias}{BASE} = $data{BASE} . '-';
245
    $ToolsetConfig{$arg_alias}{CC_OPTS} = $data{CFLAGS};
246
    $ToolsetConfig{$arg_alias}{CC_OPTSP} = $data{CFLAGSP};
247
    $ToolsetConfig{$arg_alias}{CC_OPTSD} = $data{CFLAGSD};
248
    $ToolsetConfig{$arg_alias}{VERSION} = $data{VERSION};
249
    $ToolsetConfig{$arg_alias}{MACHINE} = $data{MACHINE};
250
    $ToolsetConfig{$arg_alias}{COMPILER_OPTIONS} = $data{COMPILER_OPTIONS};
251
}
252
 
253
#.. Cross compile support
254
#
227 dpurdie 255
#   Toolchain=root,[bin]
256
#
257
    if ( $arg_alias )
258
    {
259
        if ( exists $ToolsetConfig{ $arg_alias } )
260
        {
369 dpurdie 261
            $GCCToolchain = $ToolsetConfig{ $arg_alias };
262
            $tools_found = (-d $GCCToolchain->{ROOT});
227 dpurdie 263
            Warning ("gcc toolset: CrossPlatform toolchain not found for: $arg_alias",
369 dpurdie 264
                     "Path: $GCCToolchain->{ROOT}" ) unless $tools_found;
227 dpurdie 265
        }
266
        else
267
        {
268
            Error("gcc toolset: CrossPlatform Alias not configured: $arg_alias");
269
        }
369 dpurdie 270
 
271
        Warning ("Uncontrolled toolchain used: $arg_alias")
272
            if ( exists($GCCToolchain->{UNCONTROLLED}) && $GCCToolchain->{UNCONTROLLED} );
227 dpurdie 273
    }
274
 
275
    #
276
    #   If no Cross compiler toolchain is found (preferred method), then attempt
277
    #   to match a native compiler. Only known targets allow a native build
278
    #
279
    unless ( $tools_found )
280
    {
281
        if ( exists ( $NativeCompilers{$GCCTarget} ))
282
        {
283
            if ( $NativeCompilers{$GCCTarget} eq $::GBE_MACHTYPE )
284
            {
285
                $tools_found = 1;
369 dpurdie 286
                $GCCToolchain = undef;
227 dpurdie 287
            }
288
        }
289
    }
290
 
291
    #
292
    #   Must have a toolset by now, either a cross compiler or Native
293
    #
294
    Error ("gcc toolset: Toolchain not found for: $GCCTarget" )
295
        unless ( $tools_found );
296
 
297
 
369 dpurdie 298
    if ( defined $GCCToolchain )
227 dpurdie 299
    {
300
        #
369 dpurdie 301
        #   Parse GCCToolchain. Potential parts to create
302
        #       GCCRoot     - Location to find the effective /usr/include directory
303
        #       GCCBin      - Path to the gcc executable
304
        #       GCCAr       - Path to the ar executable
4034 dpurdie 305
        #       GCCFlags    - Additional compiler flags. Also Production and Debug
227 dpurdie 306
        #
369 dpurdie 307
        $GCCRoot = $GCCToolchain->{ROOT};
308
        $GCCBin = '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'gcc';
309
        $GCCAr =  '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'ar';
373 dpurdie 310
        $GCCObjCopy =  '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'objcopy';
369 dpurdie 311
        $GCCFlags = $GCCToolchain->{CC_OPTS};
4034 dpurdie 312
        $GCCFlagsP = $GCCToolchain->{CC_OPTSP};
313
        $GCCFlagsD = $GCCToolchain->{CC_OPTSD};
3967 dpurdie 314
        $PkgArch = $GCCToolchain->{PACKAGE_ARCH};
227 dpurdie 315
    }
316
    else
317
    {
373 dpurdie 318
        $GCCRoot = '/usr';
319
        $GCCBin = 'gcc';
320
        $GCCAr = 'ar';
321
        $GCCObjCopy =  'objcopy';
227 dpurdie 322
    }
323
 
324
#.. Define GCC environment
325
#
326
    PlatformDefine( "
327
#################################################
328
# GCC toolchain definitions 
329
#
330
#..");
369 dpurdie 331
    PlatformDefine( "GCC_TARGET         := $GCCTarget" );
332
    PlatformDefine( "GCC_ROOT           := $GCCRoot" );
333
    PlatformDefine( "GCC_CC             := $GCCBin" );
334
    PlatformDefine( "GCC_AR             := $GCCAr" );
373 dpurdie 335
    PlatformDefine( "GCC_OBJCOPY        := $GCCObjCopy" );
369 dpurdie 336
    PlatformDefine( "GCC_CFLAGS         := $GCCFlags" ) if defined $GCCFlags;
4034 dpurdie 337
    PlatformDefine( "GCC_CFLAGSP        := $GCCFlagsP" ) if defined $GCCFlagsP;
338
    PlatformDefine( "GCC_CFLAGSD        := $GCCFlagsD" ) if defined $GCCFlagsD;
369 dpurdie 339
 
227 dpurdie 340
    #
341
    #   Required since this toolset advertises: ScmToolsetCompilerPath
342
    #
369 dpurdie 343
    PlatformDefine( "SCM_COMPILERPATH   := \$\{GCC_CC\}" );
3967 dpurdie 344
 
345
    #
346
    #   Sanity checking
347
    #
348
    PlatformDefine( "GCC_EVERSION       := " . $GCCToolchain->{VERSION} ) if defined $GCCToolchain->{VERSION};
349
    PlatformDefine( "GCC_EMACHINE       := " . $GCCToolchain->{MACHINE} ) if defined $GCCToolchain->{MACHINE};
350
 
351
    #
352
    #   Option indication of packaging architecture
353
    #   Used by non-embedded systems for packaging. See debian_packager
354
    #
355
    PlatformDefine( "PACKAGE_ARCH       := $PkgArch" ) if (defined $PkgArch);
369 dpurdie 356
    PlatformDefine( "" );
227 dpurdie 357
 
358
#.. Piece the world together
359
#
3967 dpurdie 360
    Init( 'gcc' );
227 dpurdie 361
    ToolsetDefines( "gcc.def" );
362
    ToolsetRules( "gcc.rul" );
363
    ToolsetRules( "standard.rul" );
364
 
4094 dpurdie 365
 
366
    PlatformDefine( "CTAGS_EXE:= ctags" );
367
    ToolsetRequire( "exctags" );                # and Exuberant Ctags
368
 
227 dpurdie 369
#   Create a standard data structure
370
#   This is a hash of hashes
371
#       The first hash is keyed by CompileOption keyword
372
#       The second hash contains pairs of values to set or remove
373
#
374
    %::ScmToolsetCompilerOptions =
375
    (
376
        #
377
        #   Control the thread model to use
378
        #   This will affect the compiler options and the linker options
379
        #
380
        'staticprogs'        => { 'STATIC_PROGS' , '1' },      # Progams link staticlly
381
        'no_staticprogs'     => { 'STATIC_PROGS' , undef },    # Default
4034 dpurdie 382
        'noversiondll'       => { 'NO_VERSIONED_DLLS', 1 },    # Matches usage elsewhere
227 dpurdie 383
    );
384
 
385
    #
386
    #   Set default options
387
    #
388
    $::ScmCompilerOpts{'STATIC_PROGS'} = undef;
4034 dpurdie 389
    $::ScmCompilerOpts{'NO_VERSIONED_DLLS'} = undef;
390
 
391
    #
392
    #   Process toolset-specfic compiler options
393
    #
394
    if ( exists $GCCToolchain->{COMPILER_OPTIONS} )
395
    {
396
        CompileOptions('*', split(',',$GCCToolchain->{COMPILER_OPTIONS}) );
397
    }
227 dpurdie 398
}
399
 
4094 dpurdie 400
###############################################################################
401
#   ToolsetCTAGS()
402
#       This subroutine takes the user options and builds the rules
403
#       required to build the CTAGS database.
404
#
405
#   Arguments:
406
#       --xxx                   No arguments currently defined
407
#
408
#   Output:
409
#       [ctags:]
410
#           $(EXCTAGS)
411
#
412
###############################################################################
227 dpurdie 413
 
4094 dpurdie 414
sub ToolsetCTAGS
415
{
416
    EXCTAGS( @_ );
417
}
418
 
419
 
227 dpurdie 420
###############################################################################
421
#   ToolsetCC( $source, $obj, \@args )
422
#       This subroutine takes the user options and builds the rule(s)
423
#       required to compile the source file 'source' to 'obj'
424
#
425
###############################################################################
426
 
427
sub ToolsetCC
428
{
429
    my( $source, $obj, $pArgs ) = @_;
430
    my( $cflags, $file ) = "";
431
 
432
    foreach $_ ( @$pArgs ) {
433
        if (/--Shared$/) {                      # Building a 'shared' object
434
            $cflags  = "$cflags \$(SHCFLAGS)";
435
        } else {
436
            Message( "CC: unknown option $_ -- ignored\n" );
437
        }
438
    }
439
 
440
    MakePrint( "\n\t\$(CC)\n" );
441
    if ( $cflags )
442
    {                                           # object specific CFLAGS
443
        MakePadded( 4, "\$(OBJDIR)/$obj.$::o:" );
444
        MakePrint( "\tCFLAGS +=$cflags\n" );
445
    }
446
 
447
    $file = StripExt( $obj );                   # Metric working file
448
    ToolsetGenerate( "\$(OBJDIR)/$file.met" );
449
}
450
 
451
 
452
###############################################################################
453
#   ToolsetCCDepend( $depend, \@sources )
454
#       This subroutine takes the user options and builds the
455
#       rule(s) required to build the dependencies for the source
456
#       files 'sources' to 'depend'.
457
#
458
###############################################################################
459
 
460
sub ToolsetCCDepend
461
{
462
    MakePrint( "\t\$(CCDEPEND)\n" );
463
}
464
 
465
 
466
###############################################################################
467
#   ToolsetCXX( $source, $obj, \@args )
468
#       This subroutine takes the user options and builds the rule(s)
469
#       required to compile the source file 'source' to 'obj'
470
#
471
###############################################################################
472
 
473
sub ToolsetCXX
474
{
475
    my( $source, $obj, $pArgs ) = @_;
476
    my( $cflags, $file ) = "";
477
 
478
    foreach $_ ( @$pArgs ) {
479
        if (/--Shared$/) {                      # Building a 'shared' object
480
            $cflags  = "$cflags \$(SHCXXFLAGS)";
481
        } else {
482
            Message( "CXX: unknown option $_ -- ignored\n" );
483
        }
484
    }
485
 
486
    MakePrint( "\n\t\$(CXX)\n" );
487
    if ( $cflags )
488
    {                                           # object specific CFLAGS
489
        MakePadded( 4, "\$(OBJDIR)/$obj.$::o:" );
490
        MakePrint( "\tCXXFLAGS +=$cflags\n" );
491
    }
492
 
493
    $file = StripExt( $obj );                   # Metric working file
494
    ToolsetGenerate( "\$(OBJDIR)/$file.met" );
495
}
496
 
497
 
498
###############################################################################
499
#   ToolsetCXXDepend( $depend, \@sources )
500
#       This subroutine takes the user options and builds the
501
#       rule(s) required to build the dependencies for the source
502
#       files 'sources' to 'depend'.
503
#
504
###############################################################################
505
 
506
sub ToolsetCXXDepend
507
{
287 dpurdie 508
    ToolsetCCDepend();
227 dpurdie 509
}
510
 
511
 
512
###############################################################################
513
#   ToolsetAS( $source, $obj, \@args )
514
#       This subroutine takes the user options and builds the rule(s)
515
#       required to compile the source file 'source' to 'obj'
516
#
517
###############################################################################
518
 
519
sub ToolsetAS
520
{
521
    MakePrint( "\n\t\$(AS)\n" );
522
}
523
 
524
sub ToolsetASDepend
525
{
526
}
527
 
528
 
529
###############################################################################
530
#   ToolsetAR( $name, \@args, \@objs )
531
#       This subroutine takes the user options and builds the rules
532
#       required to build the library 'name'.
533
#
534
#   Arguments:
535
#       n/a
536
#
537
#   Output:
538
#       $(BINDIR)/name$.${a}:   .... ]
539
#           $(AR)
540
#
541
#       name_ld += ...  Linker command file
542
#           :
543
#
544
#       name_dp += ...  Dependency list
545
#           :
546
#
547
###############################################################################
548
 
549
sub ToolsetAR
550
{
551
    my( $name, $pArgs, $pObjs ) = @_;
552
 
553
#.. Parse arguments
554
#
555
    foreach $_ ( @$pArgs )
556
    {
557
        Message( "AR: unknown option $_ -- ignored\n" );
558
    }
559
 
560
#.. Target
561
#
562
    MakePrint( "#.. Library ($name)\n\n" );     # label
563
 
564
    MakeEntry( "\$(LIBDIR)/$name\$(GBE_TYPE).$::a:\t",
565
        "", "\\\n\t\t", ".$::o", @$pObjs );
566
 
567
#.. Build library rule (just append to standard rule)
568
#
569
    MakePrint( "\n\t\$(AR)\n\n" );
570
}
571
 
572
 
573
###############################################################################
574
#   ToolsetARMerge( $name, \@args, \@libs )
575
#       This subroutine takes the user options and builds the rules
576
#       required to build the library 'name' by merging the specified
577
#       libaries
578
#
579
#   Arguments:
580
#       --xxx                   No arguments currently defined
581
#
582
#   Output:
583
#       [ $(LIBDIR)/name$.${a}:   .... ]
584
#           ...
585
#
586
###############################################################################
587
 
588
sub ToolsetARMerge
589
{
590
    MakePrint( "\n\t\$(ARMERGE)\n\n" );
591
}
592
 
593
 
594
###############################################################################
289 dpurdie 595
#   ToolsetSHLD( $name, \@args, \@objs, \@libraries, $ver )
227 dpurdie 596
#       This subroutine takes the user options and builds the rules
339 dpurdie 597
#       required to link the Shared Library 'name'.
227 dpurdie 598
#
599
#   Arguments:
600
#   n/a
601
#
602
#   Output:
603
#       $(LIBDIR)/name:     $(LIBDIR)/shared
604
#           ln -s $shared $name
605
#
606
#       $(LIBDIR)/name.dep: $(GBE_OBJDIR)
607
#       $(LIBDIR)/name.dep: $(GBE_LIBDIR)
608
#       $(LIBDIR)/name.dep: $(GBE_PLATFORM).mk
609
#           $(SHLDDEPEND)
610
#
611
#       $(LIBDIR)/shared:   SHNAME=name
612
#       $(LIBDIR)/shared:   SHBASE=base
613
#       $(LIBDIR)/shared:   $(LIBDIR)/name.dep  \
614
#           $(OBJECTS)
615
#                           
616
#       ifneq "$(findstring $(IFLAG),23)" ""
617
#       -include            "$(LIBDIR)/name.dep"
618
#       endif
619
#
620
#       name_ld += ...
621
#           :
622
#
623
###############################################################################
624
 
625
sub ToolsetSHLD
626
{
289 dpurdie 627
    my( $name, $pArgs, $pObjs, $pLibs, $ver ) = @_;
373 dpurdie 628
    my( $linkname, $soname, $shared, $dbgname, $def, $def_pref, $multi_scan );
4034 dpurdie 629
    my $sosuffix;
630
    my $noVersionedLib = $::ScmCompilerOpts{'NO_VERSIONED_DLLS'};
227 dpurdie 631
 
4034 dpurdie 632
 
227 dpurdie 633
#.. Parse arguments
634
#
635
    foreach $_ ( @$pArgs )
636
    {
637
        if (/^--Def=(.*?)(\,(.*))?$/) {         # Library definition
638
            #
639
            #   Locate the Def file.
640
            #   If it is a generate file so it will be in the SRCS hash
641
            #   Otherwise the user will have to use Src to locate the file
642
            #
643
            $def = MakeSrcResolve($1);
644
            $def_pref = '';
645
            if ( $1 =~ m~\.def$~ ) {
646
                $def_pref = '--version-script='; # Old def file
647
            }
648
        } elsif ( /^--MultiScan/i ) {
649
            $multi_scan = 1;
650
 
651
        } elsif ( /^--NoMultiScan/i ) {
652
            $multi_scan = 0;
653
 
339 dpurdie 654
        } elsif ( /^--SoNameSuffix=(.*)/i ) {
655
            $sosuffix = $1;
656
 
4034 dpurdie 657
        } elsif (/^--NoVersionDll/i) {
658
            $noVersionedLib = 1;
659
 
227 dpurdie 660
        } else {
661
            Message( "SHLD: unknown option $_ -- ignored\n" );
662
        }
663
    }
664
 
4034 dpurdie 665
    #
666
    # Determine the 'soname' in none has been provided
667
    #
668
    $sosuffix = '.' . $ver
669
        unless ( defined $sosuffix );
670
    $sosuffix = ''
671
        if ( $noVersionedLib );
672
 
339 dpurdie 673
#.. Various library names
227 dpurdie 674
#
339 dpurdie 675
    $linkname = "$name\$(GBE_TYPE).$::so";
4034 dpurdie 676
    $shared = $noVersionedLib ? $linkname : "$linkname.$ver";
339 dpurdie 677
    $soname = "$linkname$sosuffix";
4034 dpurdie 678
 
373 dpurdie 679
    my $shared_path = "\$(LIBDIR)/${shared}";
680
    my $dbg_path =  $shared_path . '.dbg';
227 dpurdie 681
 
682
#.. Cleanup rules
683
#
684
#   map     Map file
685
#   ln      Link from LIBDIR to BINDIR
686
#
261 dpurdie 687
    ToolsetGenerate( "\$(LIBDIR)/${name}.map" );
688
    ToolsetGenerate( "\$(LIBDIR)/${shared}" );
339 dpurdie 689
    ToolsetGenerate( "\$(BINDIR)/${soname}" );
373 dpurdie 690
    ToolsetGenerate( $dbg_path );
227 dpurdie 691
 
692
#.. Build rules
693
#
694
#   name        Base name
695
#   shared      Library name, includes GBE_TYPE specification
696
#
697
    my ($io) = ToolsetPrinter::New();
335 dpurdie 698
    my $dep = $io->SetShldTarget($shared);
227 dpurdie 699
 
700
    $io->Label( "Shared library", $name );
339 dpurdie 701
    PackageShlibAddFiles( $name, "\$(LIBDIR)/$shared" );
373 dpurdie 702
    PackageShlibAddFiles( $name, $dbg_path );
4034 dpurdie 703
 
227 dpurdie 704
    $io->Prt( "\$(LIBDIR)/${shared}:\tSHBASE=${name}\n" );
339 dpurdie 705
    $io->Prt( "\$(LIBDIR)/${shared}:\tSHNAME=${soname}\n" );
706
    $io->Prt( "\$(LIBDIR)/${shared}: \\\n\t\t${dep}" );
321 dpurdie 707
    $io->Entry( "", "", " \\\n\t\t", ".$::o", @$pObjs );
227 dpurdie 708
    $io->Prt( "\\\n\t\t$def" ) if($def);
373 dpurdie 709
    $io->Prt( "\n\t\$(SHLD)" );
710
    $io->Prt( "\n\t\$(call LDSTRIP,$shared_path,$dbg_path)\n\n" );
321 dpurdie 711
 
339 dpurdie 712
#
713
#   Create soft links
714
#       'Real Name' to its 'Link Name'
715
#       'Real Name' to 'SoName' in the BINDIR (for testing I think)
716
#       'Real Name' to 'SoName' in the LIBDIR (if different)
717
#
4034 dpurdie 718
    if ( $shared ne $linkname)
719
    {
720
        $io->Label( "Shared library Symbolic Links", $name );
721
        PackageShlibAddFiles( $name, "\$(LIBDIR)/$linkname" );
722
        $io->Prt( "\$(LIBDIR)/$linkname:\t\\\n" .
723
                  "\t\t\$(GBE_BINDIR)\\\n" .
724
                  "\t\t\$(LIBDIR)/${shared}\n" .
725
                  "\t\$(AA_PRE)(rm -f \$@; ln -s ./$shared \$@)\n\n" );
726
    }
727
 
728
    $io->Label( "Shared library BINDIR Symbolic Links", $name );
729
    PackageShlibAddFiles( $name, "\$(BINDIR)/$soname" );
730
    $io->Prt( "\$(BINDIR)/$soname:\t\\\n" .
339 dpurdie 731
              "\t\t\$(GBE_BINDIR)\\\n" .
732
              "\t\t\$(LIBDIR)/${shared}\n" .
4034 dpurdie 733
              "\t\$(AA_PRE)(rm -f \$@; ln -s ../\$(LIBDIR)/$shared \$@)\n\n" );
339 dpurdie 734
 
4034 dpurdie 735
    if ( $soname ne $shared )
339 dpurdie 736
    {
737
        $io->Label( "Shared library SoName Symbolic Links", $name );
738
        PackageShlibAddFiles( $name, "\$(LIBDIR)/$soname" );
739
        $io->Prt( "\$(LIBDIR)/$soname:\t\\\n" .
740
                  "\t\t\$(GBE_LIBDIR)\\\n" .
741
                  "\t\t\$(LIBDIR)/${shared}\n" .
742
                  "\t\$(AA_PRE)(rm -f \$@; ln -s ./$shared \$@)\n" );
743
    }
744
 
227 dpurdie 745
#.. Linker command file
746
#
747
#       Now the fun part... piecing together a variable $(name_shld)
748
#       which ends up in the command file.
749
#
339 dpurdie 750
    $io->Newline();
227 dpurdie 751
    $io->SetTag( "${name}_shld" );              # command tag
752
    $io->SetTerm( "\n" );
753
 
754
    $io->Label( "Linker commands", $name );     # label
755
 
756
                                                # object list
757
    $io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );
758
 
759
    ToolsetLibStd( $pLibs );                    # push standard libraries
760
 
761
    $io->Cmd( "-Wl,$def_pref$def" ) if ($def);
762
 
763
    $io->Cmd( "-Wl,--start-group" ) if ($multi_scan);
764
    $io->LibList( $name, $pLibs, \&ToolsetLibRecipe );
765
    $io->Cmd( "-Wl,--end-group" ) if ($multi_scan);
766
 
767
    $io->Newline();
768
 
335 dpurdie 769
    #.. Dependency link,
770
    #   Create a library dependency file
771
    #       Create command file to build applicaton dependency list
772
    #       from the list of dependent libraries
773
    #
774
    #       Create makefile directives to include the dependency
775
    #       list into the makefile.
776
    #
777
    $io->DepRules( $pLibs, \&ToolsetLibRecipe, "\$(LIBDIR)/${shared}" );
339 dpurdie 778
    $io->SHLDDEPEND($name, $soname);
227 dpurdie 779
}
780
 
781
 
782
###############################################################################
271 dpurdie 783
# Function        : ToolsetLD
227 dpurdie 784
#
271 dpurdie 785
# Description     : Takes the user options and builds the rules required to
786
#                   link the program 'name'.
227 dpurdie 787
#
271 dpurdie 788
# Inputs          : $name           - base name of the program
789
#                   $pArgs          - Ref to program arguments
790
#                   $pObjs          - Ref to program objects
791
#                   $pLibs          - Ref to program library list
227 dpurdie 792
#
271 dpurdie 793
# Returns         : Nothing
227 dpurdie 794
#
271 dpurdie 795
# Output:         : Rules and recipes to create a program
796
#                       Create program rules and recipes
797
#                       Create linker input script
798
#                       Create library dependency list
799
#                       Include library dependency information
227 dpurdie 800
#
801
sub ToolsetLD
802
{
803
    my( $name, $pArgs, $pObjs, $pLibs ) = @_;
804
    my $static = $::ScmCompilerOpts{'STATIC_PROGS'};
805
    my $multi_scan;
806
 
807
#.. Parse arguments
808
#
809
    foreach $_ ( @$pArgs )
810
    {
811
        if ( m/^--Static$/ ) {
812
            $static = 1;
813
 
814
        } elsif ( m/^--Shared/ ) {
815
            $static = 0;
816
 
817
        } elsif ( /^--MultiScan/i ) {
818
            $multi_scan = 1;
819
 
820
        } elsif ( /^--NoMultiScan/i ) {
821
            $multi_scan = 0;
822
 
823
        } else {
824
            Message( "LD: unknown option $_ -- ignored\n" );
825
        }
826
    }
827
 
271 dpurdie 828
#.. Names of programs and components
829
#
830
    my $base = "\$(BINDIR)/${name}";
831
    my $full = $base . $::exe;
832
    my $map  = $base . '.map';
833
    my $ld  =  $base . '.ld';
373 dpurdie 834
    my $dbg =  $base . '.dbg';
271 dpurdie 835
 
227 dpurdie 836
#.. Cleanup rules
837
#
271 dpurdie 838
    ToolsetGenerate( $ld );
839
    ToolsetGenerate( $map );
373 dpurdie 840
    ToolsetGenerate( $dbg );
227 dpurdie 841
 
842
#.. Build rules
843
#
844
    my ($io) = ToolsetPrinter::New();
335 dpurdie 845
    my $dep = $io->SetLdTarget( $name );
227 dpurdie 846
 
271 dpurdie 847
    $io->Prt( "$full : $dep " );
848
    $io->Entry( "", "", "\\\n\t", ".$::o ", @$pObjs );
373 dpurdie 849
    $io->Prt( "\n\t\$(LD)" );
850
    $io->Prt( "\n\t\$(call LDSTRIP,$full,$dbg)\n\n" );
227 dpurdie 851
 
271 dpurdie 852
 
227 dpurdie 853
#.. Linker command file
854
#
855
#       Now the fun part... piecing together a variable $(name_ld)
856
#       which ends up in the command file.
857
#
858
    $io->SetTag( "${name}_ld" );                # macro tag
859
    $io->SetTerm( "\n" );
860
 
861
    $io->Label( "Linker commands", $name );     # label
862
 
863
    $io->Cmd( "-static" ) if ($static);         # Link as a static program
864
 
865
                                                # object list
866
    $io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );
867
 
868
    ToolsetLibStd( $pLibs );                    # push standard libraries
869
 
870
                                                # library list
871
    $io->Cmd( "-Wl,--start-group" ) if ($multi_scan);
872
    $io->LibList( $name, $pLibs, \&ToolsetLibRecipe );
873
    $io->Cmd( "-Wl,--end-group" ) if ($multi_scan);
874
 
875
    $io->Newline();
876
 
335 dpurdie 877
    #.. Dependency link,
878
    #   Create a library dependency file
879
    #       Create command file to build applicaton dependency list
880
    #       from the list of dependent libraries
881
    #
882
    #       Create makefile directives to include the dependency
883
    #       list into the makefile.
884
    #
885
    $io->DepRules( $pLibs, \&ToolsetLibRecipe, $base );
886
    $io->LDDEPEND();
271 dpurdie 887
 
888
#.. Package up the program and other artifacts
889
#
890
    PackageProgAddFiles ( $name, $full );
373 dpurdie 891
    PackageProgAddFiles ( $name, $dbg );
271 dpurdie 892
 
227 dpurdie 893
}
894
 
895
 
896
########################################################################
897
#
898
#   Push standard "system" libraries. This is a helper function
899
#   used within this toolset.
900
#
901
#   Arguments:
902
#       $plib       Reference to library array.
903
#
904
########################################################################
905
 
906
sub ToolsetLibStd
907
{
908
}
909
 
910
 
911
########################################################################
912
#
913
#   Generate a linker object recipe.  This is a helper function used 
914
#   within this toolset.
915
#
916
#   Arguments:
917
#       $io         I/O stream
918
#
919
#       $target     Name of the target
920
#
921
#       $obj        Library specification
922
#
923
########################################################################
924
 
925
sub ToolsetObjRecipe
926
{
927
    my ($io, $target, $obj) = @_;
928
 
929
    $io->Cmd( "\$(strip $obj).$::o" );
930
}
931
 
932
 
933
###############################################################################
934
#
935
#   Parse a linker lib list
936
#   This is a helper function used within this toolset
937
#
938
#   Arguments:
939
#       $target     Name of the target
940
#
941
#       $lib        Library specification
942
#
943
#       $tag        Tag (user specified)
944
#
945
#       $dp         If building a depend list, the full target name.
946
#
947
###############################################################################
948
 
949
sub ToolsetLibRecipe
950
{
951
    my ($io, $target, $lib, $dp) = @_;
952
 
953
    if ( ! defined($dp) ) {                     # linker
954
        $lib =~ s/^lib//;                       # .. remove leading 'lib'
955
        $io->Cmd( "-l$lib" );
956
 
957
    } else {                                    # depend
958
        $io->Cmd( "$dp:\t@(vlib2,$lib,GCC_LIB)" );
959
 
960
    }
961
}
962
 
963
#.. Successful termination
964
1;
965