Subversion Repositories DevTools

Rev

Rev 3559 | Blame | Compare with Previous | Last modification | View Log | RSS feed

# -*- mode: perl; indent-width: 4; show-tabs: yes; -*-
#
# Module name   : Sunworks
# Module type   : Makefile system
# Compiler(s)   : ANSI C
# Environment(s): CC
#   
# Description:
#   Sunworks C/C++ toolset
#
#.............................................................................

use strict;
use warnings;
use JatsError;

#
#   Table to provide the location of SUNWSPRO_SC
#   This is hardcoded ( not good ) based on build machine
#
#       Key: StudioIdentifier
#                   SunWorkshop6.1          - Solaris8  32 bit builds
#                   SunStudio11             - Solaris10 32 bit builds
#                   SunStudio12.1           - Solaris10 64 bit builds
#       Key: build machine type
#     Value: Per machine-type data
#
#   Per machine type data is a hash
#       archiver        - Path to archiver
#       compiler        - Path to the compiler
#       misalign{32|64} - Path (relative to compiler) to the misalign obj file
#                         If not present then misalign not supported
#
my $SunProData;
my $SunMisalignObject;
my %SunProLocation = (
    'solaris10_sparc32' => { 'SunStudio11' =>
                                {   'compiler'   => '/opt/SUNWspro',
                                    'misalign32' => 'prod/lib/misalign.o',
                                    'misalign64' => 'prod/lib/v9/misalign.o',
                                    'archiver'   => '/usr/ccs/bin',
                                },
                             'SunStudio12.1' =>
                                {   'compiler'   => '/opt/sunstudio12.1',
                                    'misalign32' => 'prod/lib/misalign.o',      # This one is OK.
                                    'misalign64' => 'prod/lib/v9/misalign.o',   # May cause link errors as the .o file is not PIC
                                    'archiver'   => '/usr/ccs/bin',
                                },
                            },

    'solaris10_x86'     =>  { 'SunStudio11' =>
                                {   'compiler'   => '/opt/SUNWspro',
                                    'archiver'   => '/usr/ccs/bin',
                                },
                             'SunStudio12.1' =>
                                {   'compiler'   => '/opt/sunstudio12.1',
                                    'archiver'   => '/usr/ccs/bin',
                                },
                            },

    'sparc'             =>  { 'SunWorkshop6.1'   =>
                                {   'compiler'   => '/opt/SUNWspro/WS6U1',
                                    'misalign32' => 'lib/misalign.o',
                                    'archiver'   => '/usr/ccs/bin',
                                },
                            }
    );

#
#   Globals
#
our $GBE_MACHTYPE;
our $s;
our $o;
our $a;
our $so;
our $exe;
our @ScmToolsetArgs;
our @ScmPlatformArgs;

##############################################################################
#   ToolsetInit()
#       Runtime initialisation
#
##############################################################################

ToolsetInit();

my $toolsetccdepend      = 0;

sub ToolsetInit
{
#.. Standard.rul requirements
#   
    $s = 'asm';
    $o = 'o';
    $a = 'a';
    $so = 'so';
    $exe = '';

#.. Toolset configuration
#
    $::ScmToolsetVersion = "1.0.0";             # our version
    $::ScmToolsetGenerate = 0;                  # GEN generate optional
    $::ScmToolsetProgDependancies = 0;          # handle Prog dependancies myself
    $::ScmToolsetSoName = 1;                    # Shared library supports SoName
    $::ScmToolsetCompilerPath = 1;              # Exports Compiler path to makefile via SCM_COMPILERPATH
    

    my $ScmToolTarget = '';
    my $ScmStudio = '';

    #
    #   Toolset args
    #
    foreach $_ ( @ScmToolsetArgs ) {
        if (/^--Target=(.*)/) {                # Target System
            $ScmToolTarget = $1;

        } elsif ( /^--Studio=(.*)/) {
            $ScmStudio = $1;

        } else {
            Message( "sunworks toolset: unknown toolset option $_ -- ignored" );
        }
    }

    #
    #   Platform arguments
    #
    foreach $_ ( @ScmPlatformArgs ) {
        if (/^--product=(.*)/) {                # GBE product
               
        } else {
            Message( "sunworks toolset: unknown platform argument $_ -- ignored" );
        }
    }

    #
    #   Sanity check
    #
    Error ("Internal: Target configuration must specify Studio version")
        unless ( $ScmStudio );

    Error ("SunWorks compiler not configured for this type of machine",
           "GBE_MACHTYPE: $GBE_MACHTYPE" )
        unless ( exists $SunProLocation{$GBE_MACHTYPE} );

    Error ("Required SunWorks/Studio not configured for this type of machine",
           "GBE_MACHTYPE: $GBE_MACHTYPE",
           "Sun Studio  : $ScmStudio" )
        unless ( exists $SunProLocation{$GBE_MACHTYPE}{$ScmStudio} );
    
    #
    #   Determine machine / Studio version specific data
    #
    $SunProData = $SunProLocation{$GBE_MACHTYPE}{$ScmStudio};

#.. Define environment
#    
    Init( "sunworks" );
    ToolsetDefines( "sunworks.def" );
    ToolsetRules  ( "sunworks.rul" );
    ToolsetRules  ( "standard.rul" );
    
#.. Cleanup rules
#
    ToolsetDirTree( "\$(LIBDIR)/SunWS_cache" );
    ToolsetDirTree( "\$(OBJDIR)/SunWS_cache" );
    ToolsetDirTree( "\$(BINDIR)/SunWS_cache" );
    ToolsetDirTree( "./SunWS_cache" );
    
    AddLibDir( '*', '/usr/lib', '--NoWarn', '--System' );

#.. Extend the CompilerOption directive
#   Create a standard data structure
#   This is a hash of hashes
#       The first hash is keyed by CompileOption keyword
#       The second hash contains pairs of values to set or remove
#
    %::ScmToolsetCompilerOptions =
    (
        #
        #   Control the thread model to use
        #   This will affect the compiler options and the linker options
        #
        'multithread'        => { 'THREADMODE' , '1' },      # -mt (default)
        'multithread_none'   => { 'THREADMODE' , undef },    # (none)
        'no_multithread'     => { 'THREADMODE' , undef },    # (none)

        'no_misalign'        => { 'MISALIGN', undef },       # (default)
        'misalign'           => { 'MISALIGN', '1' },
    );

    #
    #   Set default options
    #
    $::ScmCompilerOpts{'THREADMODE'} = '1';


    #
    #   Ensure that we know where the compiler and archiver are
    #
    my $sunpro = $SunProData->{compiler};
    ToolsetDefine ( "SUNWSPRO_SC  = $sunpro" );

    my $ar_path = $SunProData->{archiver};
    ToolsetDefine ( "AR_PATH  = $ar_path" );

    #
    #   Specify definitions to support 32 and 64 bit compilation
    #   Default operation is only intended for existing (solaris8) work
    #
    if ( ($ScmToolTarget =~ m/32$/) )
    {
        ToolsetDefine ( "COMPILE32  = 1" );
        $SunMisalignObject = $SunProData->{'misalign32'};
    }
    elsif ( ($ScmToolTarget =~ m/64$/) )
    {
        ToolsetDefine ( "COMPILE64  = 1" );
        $SunMisalignObject = $SunProData->{'misalign64'};
    }
    else
    {
        $SunMisalignObject = $SunProData->{'misalign32'};
    }

    #
    #   Allow SPARC and X86 compilation options to differ
    #
    my $isa_sparc = ( $GBE_MACHTYPE =~ m/sparc/i ) ? 1 : 0;
    ToolsetDefine ( "ISA_SPARC  = 1" ) if ($isa_sparc);

    #   Required since this toolset advertises: ScmToolsetCompilerPath
    #   Used by shell builder
    #
    PlatformDefine( "SCM_COMPILERPATH   := \$\{SUNWSPRO_SC\}/bin/cc" );
    PlatformDefine( "" );

}

##############################################################################
#   ToolsetPreprocess()
#       Process collected data before the makefile is generated
#       This, optional, routine is called from within MakefileGenerate()
#       It allows the toolset to massage any of the collected data before
#       the makefile is created
#
##############################################################################

sub ToolsetPreprocess
{
    #
    #   If the machine does not support misalignment and the user has requested
    #   it, then kill the option - it makes life easier later.
    #
    unless ( $SunMisalignObject )
    {
        if ( $::ScmCompilerOpts{'MISALIGN'} )
        {
            Warning("Platform does not support MISALIGN option. Will be ignored");
            delete $::ScmCompilerOpts{'MISALIGN'};
        }
    }
}

###############################################################################
#   ToolsetCC( $source, $obj, \@args )
#       This subroutine takes the user options and builds the rule(s)
#       required to compile the source file 'source' to 'obj'
#
###############################################################################

sub ToolsetCC
{
    my( $source, $obj, $pArgs ) = @_;
    my( $cflags ) = "";

    Debug( "CC:  $source -> $obj" );
    foreach ( @$pArgs ) {
        Debug( "option:    $_" );
        if ( /--Shared$/ ) {                    # Building a 'shared' object
            $cflags = "$cflags \$(SHCFLAGS)";
            Debug( "CC:    as shared object" );

        } else {                                # unknown option
            Message( "CC: unknown option $_ -- ignored\n" );
        }
    }
                   
    MakePrint( "\n\t\$(CC)\n" );
    if ( $cflags )
    {                                           # object specific CFLAGS
        MakePadded( 4, "\$(OBJDIR)/$obj.${o}:" );
        MakePrint( "\tCFLAGS +=$cflags\n" );
    }
}


###############################################################################
#   ToolsetCCDepend( $depend, \@sources )
#       This subroutine takes the user options and builds the
#       rule(s) required to build the dependencies for the source
#       files 'sources' to 'depend'.
#
###############################################################################

sub ToolsetCCDepend
{
    MakePrint( "\t\$(CCDEPEND)\n" );
    $toolsetccdepend = 1;
}


###############################################################################
#   ToolsetCXX( $source, $obj, \@args )
#       This subroutine takes the user options and builds the rule(s)
#       required to compile the source file 'source' to 'obj'
#
###############################################################################

sub ToolsetCXX
{
    my( $source, $obj, $pArgs ) = @_;
    my( $cflags ) = "";

    Debug( "CCX: $source -> $obj" );
    foreach ( @$pArgs ) {
        Debug( "option:    $_" );
        if ( /--Shared$/ ) {                    # Building a 'shared' object
            $cflags = "$cflags \$(SHCXXFLAGS)";
            Debug( "CCX:    as shared object" );

        } else {
            Message( "CCX: unknown option $_ -- ignored\n" );
        }
    }
                 
    MakePrint( "\n\t\$(CXX)\n" );
    if ( $cflags )
    {                                           # object specific CFLAGS
        MakePadded( 4, "\$(OBJDIR)/$obj.${o}:" );
        MakePrint( "\tCXXFLAGS +=$cflags\n" );
    }
}


###############################################################################
#   ToolsetCXXDepend( $depend, \@sources )
#       This subroutine takes the user options and builds the
#       rule(s) required to build the dependencies for the source
#       files 'sources' to 'depend'.
#
###############################################################################

sub ToolsetCXXDepend
{
    MakePrint( "\t\$(CCDEPEND)\n" )
        if ( $toolsetccdepend == 0 );
}


###############################################################################
#   ToolsetAS( $source, $obj, \@args )
#       This subroutine takes the user options and builds the rule(s)
#       required to compile the source file 'source' to 'obj'
#
###############################################################################

sub ToolsetAS
{
    my( $source, $obj, $pArgs ) = @_;

    foreach $_ ( @$pArgs ) {
        Message( "CC: unknown option $_ -- ignored\n" );
    }

    MakePrint( "\n\t\$(AS)\n" );
}

sub ToolsetASDepend
{
}


###############################################################################
#   ToolsetAR( $name, \@args, \@objs )
#       This subroutine takes the user options and builds the rules
#       required to build the library 'name'.
#
#   Arguments:
#
#   Options:
#       n/a
#
#   Output:
#       [ $(LIBDIR)/name$.${a}:   .... ]
#           $(AR)
#
###############################################################################

sub ToolsetAR
{
    my( $name, $pArgs, $pObjs ) = @_;

#.. Parse arguments
#
    foreach $_ ( @$pArgs ) {
        Message( "AR: unknown option $_ -- ignored\n" );
    }

#.. Standard library builds
#
    MakeEntry( "\$(LIBDIR)/$name\$(GBE_TYPE).${a}:\t",
                  "", "\\\n\t\t", ".${o} ", @$pObjs );
    MakePrint( "\n\t\$(AR)\n\n" );
}


###############################################################################
#   ToolsetARMerge( $name, \@args, \@libs )
#       This subroutine takes the user options and builds the rules
#       required to build the library 'name' by merging the specified
#       libaries
#
#   Arguments:
#       --xxx                   No arguments currently defined
#
#   Output:
#       [ $(LIBDIR)/name$.${a}:   .... ]
#           ...
#
###############################################################################

sub ToolsetARMerge
{
    MakePrint( "\n\t\$(ARMERGE)\n\n" );
}


###############################################################################
#   ToolsetSHLD( $name, \@args, \@objs, \@libraries, $ver )
#       This subroutine takes the user options and builds the rules
#       required to link the program 'name'.
#
#   Arguments:
#       --WithMisalign
#
#   Output:
#       $(LIBDIR)/name:         $(LIBDIR)/shared
#               ln -s $shared $name
#
#       $(LIBDIR)/name.dep:     $(GBE_PLATFORM).mk
#               $(SHLDDEPEND)
#
#       $(LIBDIR)/shared:       SHLIB=name
#       $(LIBDIR)/shared:       $(LIBDIR)/name.dep      \
#               $(OBJECTS)
#                               
#       ifneq "$(findstring $(IFLAG),23)" ""
#       -include                "$(LIBDIR)/name.dep"
#       endif
#
#       name_ld += ...
#           :
#
###############################################################################

sub ToolsetSHLD
{
    my( $name, $pArgs, $pObjs, $pLibs, $ver ) = @_;
    my( $linkname, $soname ,$shared, $merge_obj );
    my $sosuffix = '';

#.. Parse arguments
#
    foreach $_ ( @$pArgs )
    {
        if ( m~^--WithMisalign~ ) {
            $merge_obj = $SunMisalignObject;

        } elsif ( /^--SoNameSuffix=(.*)/i ) {
            $sosuffix = $1;

        } else {
            Message( "SHLD: unknown option $_ -- ignored\n" );
        }
    }

#.. Various library names
#
    $linkname = "$name\$(GBE_TYPE).$::so";
    $shared = "$linkname.$ver";
    $soname = "$linkname$sosuffix";

#.. Cleanup rules
#
#   map     Map file
#   ln      Link from LIBDIR to BINDIR
#
    ToolsetGenerate( "\$(LIBDIR)/${shared}.map" );
    ToolsetGenerate( "\$(LIBDIR)/${shared}" );
    ToolsetGenerate( "\$(BINDIR)/${soname}" );
    ToolsetDirTree( "\$(LIBDIR)/${name}/SunWS_cache" );
    ToolsetDirTree( "\$(OBJDIR)/${name}/SunWS_cache" );

#.. Build rules
#
#   name        Base name
#   shared      Library name, includes GBE_TYPE specification
#
    my ($io) = ToolsetPrinter::New();
    my $dep = $io->SetShldTarget($shared);

    $io->Label( "Shared library", $name );
    PackageShlibAddFiles( $name, "\$(LIBDIR)/$shared" );
    
    $io->Prt( "\$(LIBDIR)/${shared}:\tSHBASE=${name}\n" );
    $io->Prt( "\$(LIBDIR)/${shared}:\tSHNAME=${soname}\n" );
    $io->Prt( "\$(LIBDIR)/${shared}: \\\n\t\t${dep}" );
    $io->Entry( "", "", " \\\n\t\t", ".$::o", @$pObjs );
    $io->Prt( "\n\t\$(SHLD)\n\n" );
    

#
#   Create soft links
#       'Real Name' to its 'Link Name'
#       'Real Name' to 'SoName' in the BINDIR (for testing I think)
#       'Real Name' to 'SoName' in the LIBDIR (if different)
#
    $io->Label( "Shared library Symbolic Links", $name );
    PackageShlibAddFiles( $name, "\$(LIBDIR)/$linkname", 'symlink=1' );
    $io->Prt( "\$(LIBDIR)/$linkname:\t\\\n" .
              "\t\t\$(GBE_BINDIR)\\\n" .
              "\t\t\$(LIBDIR)/${shared}\n" .
              "\t\$(AA_PRE)(rm -f \$@; ln -s $shared \$@)\n" .
              "\t\$(AA_PRE)(rm -f \$(BINDIR)/$soname; ln -s ../\$(LIBDIR)/$shared \$(BINDIR)/$soname)\n\n" );

    if ( $soname ne $shared && $soname ne $linkname)
    {
        $io->Label( "Shared library SoName Symbolic Links", $name );
        PackageShlibAddFiles( $name, "\$(LIBDIR)/$soname", 'symlink=1' );
        $io->Prt( "\$(LIBDIR)/$soname:\t\\\n" .
                  "\t\t\$(GBE_LIBDIR)\\\n" .
                  "\t\t\$(LIBDIR)/${shared}\n" .
                  "\t\$(AA_PRE)(rm -f \$@; ln -s $shared \$@)\n" );
    }

#.. Linker command file
#
#       Now the fun part... piecing together a variable $(name_shld)
#       which ends up in the command file.
#
    $io->Newline();
    $io->SetTag( "${name}_shld" );              # command tag
    $io->SetTerm( "\n" );

    $io->Label( "Linker commands", $name );     # label

                                                # object list
    $io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );

    if ( $merge_obj )
    {
        $io->PrtLn( "ifdef MISALIGN" );
        $io->Cmd( "\$(SUNWSPRO_SC)/$merge_obj" );
        $io->PrtLn( "endif" );
    }

    ToolsetLibStd( $pLibs );                    # push standard libraries

    $io->LibList( $name, $pLibs, \&ToolsetLibRecipe );

    $io->Newline();

    #.. Dependency link,
    #   Create a library dependency file
    #       Create command file to build applicaton dependency list
    #       from the list of dependent libraries
    #
    #       Create makefile directives to include the dependency
    #       list into the makefile.
    #
    $io->DepRules( $pLibs, \&ToolsetLibRecipe, "\$(LIBDIR)/${shared}" );
    $io->SHLDDEPEND($name, $soname);
}


######################################################
#   ToolsetLD( $name, \@args, \@objs, \@libraries )
#       This subroutine takes the user options and builds the rules
#       required to link the program 'name'.
#
#   Arguments:
#       n/a
#
#   Output:
#       $(BINDIR)/name:
#                       $(BINDIR)/name.dep
#           $(LD)
#       $(BINDIR)/name.dep:     $(GBE_PLATFORM).mk
#               $(LDDEPEND)
#
#       ifeq "$(IFLAG)" "3"
#       -include        "$(BINDIR)/name.dep"
#       endif
#
#       name_ld += ...
#           :
#
###############################################################################

sub ToolsetLD
{
    my( $name, $pArgs, $pObjs, $pLibs ) = @_;

#.. Parse arguments
#
    foreach $_ ( @$pArgs )
    {
        Message( "LD: unknown option $_ -- ignored\n" );
    }

#.. Names of programs and components
#
    my $base = "\$(BINDIR)/${name}";
    my $full = $base . $::exe;
    my $map  = $base . '.map';
    my $ld  =  $base . '.ld';
    
#.. Cleanup rules
#
#       dep     Dependency file
#       map     Mape file
#
    ToolsetGenerate( $map );


    my ($io) = ToolsetPrinter::New();
    my $dep =$io->SetLdTarget( $name );

#.. Build rules
#

    $io->Prt( "$full : $dep " );
    $io->Entry( "", "", "\\\n\t", ".$::o ", @$pObjs );
    $io->Prt( "\n\t\$(LD)\n\n" );


#.. Linker command file
#
#       Now the fun part... piecing together a variable $(name_ld)
#       which ends up in the command file.
#
    $io->SetTag( "${name}_ld" );                        # macro tag
    $io->SetTerm( "\n" );

    $io->Label( "Linker commands", $name );             # label
    $io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );  # object list
    ToolsetLibStd( $pLibs );                            # push standard libraries
    $io->LibList( $name, $pLibs, \&ToolsetLibRecipe );  # library list
    $io->Newline();

#.. Dependency link,
#   Create a library dependency file
#       Create command file to build applicaton dependency list
#       from the list of dependent libraries
#
#       Create makefile directives to include the dependency
#       list into the makefile.
#
    $io->DepRules( $pLibs, \&ToolsetLibRecipe, $base );
    $io->LDDEPEND();                                    # standard LDDEPEND rules


#.. Package up the program and other artifacts
#
    PackageProgAddFiles ( $name, $full );

}


########################################################################
#
#   Push standard "system" libraries. This is a helper function
#   used within this toolset.
#
#   Arguments:
#       $plib       Reference to library array.
#
########################################################################

sub ToolsetLibStd
{
}

########################################################################
#
#   Generate a linker object recipe.  This is a helper function used 
#   within this toolset.
#
#   Arguments:
#       $io         I/O stream
#
#       $target     Name of the target
#
#       $obj        Library specification
#
########################################################################

sub ToolsetObjRecipe
{
    my ($io, $target, $obj) = @_;

    $io->Cmd( "\$(strip $obj).$::o" );
}


###############################################################################
#
#   Parse a linker lib list
#   This is a helper function used within this toolset
#
#   Arguments:
#       $target     Name of the target
#
#       $lib        Library specification
#
#       $tag        Tag (user specified)
#
#       $dp         If building a depend list, the full target name.
#
###############################################################################

sub ToolsetLibRecipe
{
    my ($io, $target, $lib, $dp) = @_;

    if ( ! defined($dp) ) {                     # linker
        $lib =~ s/^lib//;                       # .. remove leading 'lib'
        $io->Cmd( "-l $lib" );
    
    } else {                                    # depend
        $io->Cmd( "$dp:\t@(vlib2,$lib,CC_LIB)" );

    }
}
#.. Successful termination

1;