Subversion Repositories DevTools

Rev

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

#..
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
#
# Module name   : JATS
# Module type   : JATS Toolset
# Compiler(s)   : Perl
# Environment(s): JATS
#
# Description:
#       This file provides Toolset initialisation and plugin functions
#       to makelib.pl2
#
# Contents:     VERIX rules as used for the Verix V SDK
#
#............................................................................#

use strict;
use warnings;
use JatsVersionUtils;

#
#   Globals
#
our $ScmBuildVersionFull;                   # Full Build Version Number


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

ToolsetInit();

sub ToolsetInit
{
    my( $version, $flavour );
    my $no_defines;
    my( @defines );
    my $board = '';

#.. Parse Toolset arguments
#
    Debug( "verix(@::ScmToolsetArgs)\n" );

    $version = 0;                               # Default (not great)
    foreach $_ ( @::ScmToolsetArgs ) {
        if (/^--Version=(.*)/) {                # Compiler version
            $version = "$1";
        } else {
            Message( "verix: unknown toolset argument $_ -- ignored" );
        }
    }

#.. Parse Platform Arguments
#
    foreach $_ ( @::ScmPlatformArgs ) {
        if (/^--product=(.*)/) {                # GBE product

        } else {
            Message( "verix: unknown platform argument $_ -- ignored" );
        }
    }


#.. Standard.rul requirements
#
    $::s = 'asm';                           # Assembler source file
    $::o = 'o';                             # Object file
    $::a = 'a';                             # Library file - Cannot build
    $::so = '';                             # Shared library - Not Supported
    $::exe = '.out';                        # Executables

#.. Toolset configuration
#
    $::ScmToolsetVersion = "1.0.0";         # our version
    $::ScmToolsetGenerate = 0;              # generate optional
    $::ScmToolsetProgDependancies = 0;      # handle Prog dependancies myself

#.. Define VERIX environment
#
    #
    #   Define initialisation targets
    #   These will be used to ensure that correct versions of the toolset are present
    #
    Init( "verix" );

    ToolsetDefine ( "#################################################" );
    ToolsetDefine ( "# VERIX V compiler version" );
    ToolsetDefine ( "#" );
    ToolsetDefine ( "#" );
    ToolsetDefines( "VERIX.DEF" );
    ToolsetRules  ( "VERIX.RUL" );
    ToolsetRules  ( "STANDARD.RUL" );

    #
    #   Other toolsets used
    #
    PlatformDefine ("LINT_COFILE\t= verix.LNT");
    PlatformDefine ("LINT_PRJ_FILE\t=lint.vrx");
    ToolsetRequire( "pclint" );                 # using pclint


#.. 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 =
    (
        'systemlib='          => { 'VRX_SYSLIBS'  ,\&AddList }, # Extend System Libs
        'incpath='            => { 'VRX_INCPATH'  ,\&AddList }, # Extend Inc Path
        'nowarn='             => { 'NOWARNLIST'   ,\&NoWarns }, # Suppress warnings
        'timeoptimization'    => { 'OPT_MODE' , 'time'  },      # Time optimize
        'spaceoptimization'   => { 'OPT_MODE' , 'space' },      # Space optimize
        'defaultoptimization' => { 'OPT_MODE' , undef },        # Default (?space)
        'noaddlibs'           => { 'ADDLINKLIBS' , undef },     # Don't add link libs
        'addlibs'             => { 'ADDLINKLIBS' , '1' },       # default
    );


    #
    #   Set default options
    #       $::ScmCompilerOpts{'xxxx'} = 'yyy';
    #
    $::ScmCompilerOpts{'VRX_SYSLIBS'} = [];
    $::ScmCompilerOpts{'VRX_INCPATH'} = [];
    $::ScmCompilerOpts{'NOWARNLIST'}  = '';
    $::ScmCompilerOpts{'OPT_MODE'}    = 'space';
    $::ScmCompilerOpts{'ADDLINKLIBS'} = '1';

}

#-------------------------------------------------------------------------------
# Function        : AddList
#
# Description     : Add a path to a list
#
# Inputs          : $key        - Name of the Option
#                   $value      - Option Value. Comma sep list of paths
#                   $ukey       - User key (within $::ScmCompilerOpts)
#
# Returns         : New sting to save
#
sub AddList
{
    my ($key, $value, $ukey) = @_;
    push  @{$::ScmCompilerOpts{$ukey}} , '$(VERIX)/' . $value;
    return $::ScmCompilerOpts{$ukey};
}

#-------------------------------------------------------------------------------
# Function        : NoWarns
#
# Description     : ScmToolsetCompilerOptions  extension function
#                   Accumulates the NoWarn options as a comma seperated list
#
# Inputs          : $key        - Name of the Option
#                   $value      - Option Value. Comma sep list of numbers
#                   $ukey       - User key (within $::ScmCompilerOpts)
#
# Returns         : New sting to save
#
sub NoWarns
{
    my ($key, $value, $ukey) = @_;
    my @NoWarnList =  split (',', $::ScmCompilerOpts{$ukey});
    UniquePush ( \@NoWarnList, split (',', $value) );
    return join ',', @NoWarnList;
}



###############################################################################
#   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
{
    ToolsetCC_common( "CC", @_ );
}

###############################################################################
#   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" );
}


###############################################################################
#   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
{
    ToolsetCC_common( "CXX", @_ );
}

###############################################################################
#   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
{
    ToolsetCCDepend();
}

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

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


    #
    #   Mark any 'lst' file for deletion
    #
    ToolsetGenerate( "\$(OBJDIR)/$obj.lst" );

    #
    #   Simple rule to create object file
    #
    MakePrint( "\n\t\$($name)\n" );
}



###############################################################################
#   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
{
    MakePrint( "\n\t\$(AS)\n" );
}

sub ToolsetASDepend
{
}

#-------------------------------------------------------------------------------
# Function        : ToolsetAR
#
# Description     : Build rules to create a static library
#
# Inputs          : $name   - Name of the output library
#                   $pArgs  - Library arguments
#                   $pObjs  - Objects to go into the library
#
# Returns         : Nothing
#

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

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

#.. Target
#
    MakePrint( "#.. Library ($name)\n\n" );     # label

    MakeEntry( "\$(LIBDIR)/$name\$(GBE_TYPE).$::a:\t",
        "", "\\\n\t\t", ".$::o", @$pObjs );

#.. Build library rule (just append to standard rule)
#
    MakePrint( "\n\t\$(AR)\n\n" );
}

#-------------------------------------------------------------------------------
# Function        : ToolsetARMerge
#
# Description     : This subroutine takes the user options and builds the rules
#                   required to build the library 'name' by merging the specified
#                   libaries
#
# Inputs          : $name   - Name of the output library
#                   $pArgs  - Library arguments
#                   $pLibs  - Libraries to be merged
#
# Returns         : Nothing
#
# Returns         : 
#

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

#-------------------------------------------------------------------------------
#   ToolsetLD( $name, \@pArgs, \@pObjs, \@pLibs )
#       This subroutine takes the user options and builds the rules
#       required to link the program 'name'.
#
#   Toolset is configured to suppress partial creation of the Package
#   Rules. This function must create the complete rule and recipe set.
#
#   Arguments:
#       $name           - Name of the output
#       $pArgs          - Ref to array of args
#       $pObjs          - Ref to array of objects
#       $pLibs          - Ref to array of libs
#
#  Options:
#       --NoAddLibs     - Do not add system libraries
#       --AddLibs       - Do add system libraries (default -ish)
#
#       --Map           - Add Map File
#       --NoMap         - No Map File (Default)
#       --Sign          - Sign file for RAM   - Default certificate name
#       --Sign=xxxx     - Sign file for RAM   - Name the certificate
#       --SignFlash      - Sign file for Flash - Default certificate name
#       --SignFlash=xxxx - Sign file for Flash - Name the certificate
#
#       --Heap=nnnn     - Set heap size
#       --Stack=nnnn    - Set Stack Size
#       --Flags=nnnn    - Set flags
#       --Debugable     - Mark as debugable
#       --NoDebugable   - Mark as non-debugable
#       --Version=n.n   - Set version
#       --Version       - Use Build Major, Minor
#       --ShowHeader    - Just show the header
#       --NoShowHeader  - Default
#
#   Output:
#       Generates makefile rules and recipes to create a program
#

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

    my $addlibs = $::ScmCompilerOpts{'ADDLINKLIBS'} ;
    my $map_file;
    my $certificate;
    my $flash;

    my $header;
    my $heap;
    my $stack;
    my $flags;
    my $debugable = 0;
    my $version;

#.. Parse arguments
#

    foreach ( @$pArgs )
    {
        if ( m{^--(No)?AddLib}i ) {
            $addlibs = ! $1;
        
        } elsif ( m {^--Sign(=(.+))?}i  ) {
            $certificate = $2 ? $2 : $name;
            $flash = 0;

        } elsif ( m {^--SignFlash(=(.+))?}i  ) {
            $certificate = $2 ? $2 : $name;
            $flash = 1;

        } elsif ( m {^--(No)?Map}i  ) {
            $map_file = ! $1;

        } elsif ( m {^--(No)?ShowHeader}i  ) {
            $header = ! $1;

        } elsif ( m {^--Heap=(\d+)}i  ) {
            $heap = $1;

        } elsif ( m {^--Stack=(\d+)}i  ) {
            $stack = $1;
            
        } elsif ( m {^--Flags=(\d+)}i  ) {
            $flags = $1;
            Error ("Header Flags must be in the range 0 ..255") if ( $flags > 255 );

        } elsif ( m {^--(No)?Debug}i  ) {
            $debugable = $1 ? 2 : 1;

        } elsif ( m {^--Version(=(.+))?}i  ) {
            my $major;
            my $minor;

            if ( $2 )
            {
                $version = $2;
                Error ("LD: Version must be in the form m.n") unless ( $version =~ m~(\d+)\.(\d+)~ );
                ( $major, $minor) = ($1, $2);
            }
            else
            {
                ($major, $minor) = SplitVersion($ScmBuildVersionFull);
                $version = "$major.$minor";
            }
            Error ("LD: Version number($version). Major number must be in the range 0 .. 255" ) if ( $major > 255 );
            Error ("LD: Version number($version). Minor number must be in the range 0 .. 255" ) if ( $minor > 255 );

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

    #
    #   Determine the target output name
    #
    my $root = "\$(BINDIR)/$name";
    my $full = $root . $::exe;
    my $map  = $root . '.map';

    #.. Packageing
    #   Have supressed default Prog building
    #   Need to specify the files to Package
    #
    PackageProgAddFiles ( $name, $full );
    PackageProgAddFiles ( $name, $map, 'Class=map' ) if $map_file;


    #.. Cleanup rules
    #
    ToolsetGenerate( $map );
    ToolsetGenerate( "$root.axf" );
    ToolsetGenerate( "$root.srt" );
    ToolsetGenerate( "$root.bak" );

    #
    #   Add standard system libraries to the complete list of libraries
    #
    push @$pLibs, 'ACT2000' if ( $addlibs );

    #.. Build rules
    #
    my ($io) = ToolsetPrinter::New();
    my $dep = $io->SetLdTarget( $name );

    #.. 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 );        # library depends rules
    $io->LDDEPEND();                                    # standard LDDEPEND rules

    #
    #   List the object files
    #   Create a definition for the objects
    #
    $io->Label( "Object files", $name );                # label
    $io->StartDef ("${name}_obj");
    $io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );
    $io->EndDef ();
    $io->Newline();

    #
    #   Define the program and its dependencies
    #   Place the .dep file first - this will ensure that failure
    #   to create this file will create an error before the object
    #   files are compiled. This makes it obvious what the error is.
    #
    $io->Label( "Program", $name );                     # label
    $io->Prt( "$full : \t$dep" );                       # Dependencies
    $io->Prt( "\\\n\t\$(${name}_obj)" .
              " \\\n\t\$(${name}_lib)\n" );

    #
    #   Recipe to build the program
    #
    $io->PrtLn( "\t\$(LD)" );

    #
    #   Append header modification recipe entries
    #
    $io->PrtLn( "\t\$(call HEADER,-q -v $version,\"Set Version: $version\")" ) if $version;
    $io->PrtLn( "\t\$(call HEADER,-q -s $stack,\"Set stack: $stack\")" ) if $stack;
    $io->PrtLn( "\t\$(call HEADER,-q -h $heap,\"Set Heap: $heap\")" ) if $heap;
    $io->PrtLn( "\t\$(call HEADER,-q -f $flags,\"Set Flags: $flags\")" ) if defined $flags;
    $io->PrtLn( "\t\$(call HEADER,-q -d,\"Mark Debugable\")" ) if $debugable == 1;
    $io->PrtLn( "\t\$(call HEADER,-q -n,\"Mark Non Debuggable\")" )if $debugable == 2;
    $io->PrtLn( "\t\$(call HEADER,,\"Show Header\")" ) if $header;
    $io->PrtLn( "");


    #.. Linker command file
    #
    #       Create a variable $(name_ld) which will be the linker
    #       command line. Use previosly defined values
    #
    $io->Label( "Linker commands", $name );         # label
    $io->StartDef ("${name}_ld");
    $io->Def( "\$(${name}_obj)" );                  # Object file list variable
    $io->Def( "\$(${name}_lib)" );                  # Library list variable
    $io->EndDef ();
    $io->Newline();

    #.. Sign the output file
    #
    #
    if ( $certificate )
    {

        my $cert = "\$(BINDIR)/$certificate.crt";
        my $sign = "$full.P7S";
        my $opts =  $flash ? '-L' : '';

        #
        #   Mark files to be built and packaged as a part of the program
        #
        ProgAddExtra ($name, $sign );
        PackageProgAddFiles ( $name, $sign );
        PackageProgAddFiles ( $name, $cert );

        #
        #   Create rule to sign the program
        #
        $io->Label( "Sign Program", $name );        # label
        $io->PrtLn( "$sign : $full" );
        $io->PrtLn( "\t\$(call FILESIGNATURE,$full,$cert,$opts)" );

        #
        #   File to clean up
        #
        ToolsetGenerate ( $sign );
        ToolsetGenerate ( $cert );
    }

}


########################################################################
#
#   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->Def( "$obj.$::o" );
}


###############################################################################
#
#   Parse a linker lib list
#   This is a helper function used within this toolset
#
#   Used to create a variable that will be fedd into 'cmdfile'
#   The output will then be included in the makefile
#   The output extends the definitions of the program being built
#   to contain the absolute pathnames to the libraries being consumed.
#
#   Arguments:
#       $io         io printer class
#
#       $target     Name of the target
#
#       $lib        Library specification
#
###############################################################################

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

    $io->Cmd( "${target}_lib += @(vglob2,$lib.$::a,LIB)" );
}

#.. Successful termination
1;