Subversion Repositories DevTools

Rev

Rev 363 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

##############################################################################
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
#
# Module name   : TOOLSET/arm251
# Module type   : Makefile system
# Environment(s):
#
# Description:
#   Arm V2.51 toolset
#   A very simple toolset to support
#       1) C compiliation
#       2) Generation of libaries
#       3) Merging of libraries
#       4) Executables
#       5) Assembler files
#
#   Does not support
#       a) Shared libraries
#
#   Based on the KEILARM32 toolset
#
##############################################################################

our @ScmToolsetArgs;

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

ToolsetInit();

sub ToolsetInit
{
        $DefFile = 'ARM251.DEF';
        $Version = "Arm V2.51";
    

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

    Error ("Unsupported compiler version: $Version")
        unless (Exists( "$::GBE_CONFIG/TOOLSET", $DefFile));

#.. Standard.rul requirements
#
    $s = 's';
    $o = 'o';
    $a = 'lib';
    $exe = '.axf';

    #
    #   Regsiter non standard files types
    #
    AddSourceType( ".$s", '.asm' );

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

#.. Define environment
#
    Init( "arm251" );

    ToolsetDefine( "#################################################" );
    ToolsetDefine( "# Compiler version" );
    ToolsetDefine( "#" );
    ToolsetDefine( "Arm Compiler Version      = \"$Version\"" );
    ToolsetDefine( "" );
    ToolsetDefine( "#" );

    ToolsetDefines( $DefFile );
    ToolsetRules  ( "arm251.rul" );
    ToolsetRules  ( "standard.rul" );

    #
    #   Extend the cleanup rule
    #
    ToolsetGenerate( '*.lst' );

#.. 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 =
    (
        'timeoptimization'    => { 'OPT_MODE' , 'time'  },      # Time optimize
        'spaceoptimization'   => { 'OPT_MODE' , 'space' },      # Space optimize
        'defaultoptimization' => { 'OPT_MODE' , undef },        # Default (?space)
    );


    #
    #   Set default options
    #       $::ScmCompilerOpts{'xxxx'} = 'yyy';
    #
    $::ScmCompilerOpts{'OPT_MODE'}    = undef;

}

###############################################################################
#   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
{
}

###############################################################################
#   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 ) = @_;

    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" );
    MakePrint( "\$(OBJDIR)/$i.${o}:\tCFLAGS +=$cflags\n" )
        if ( $cflags );
}

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

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

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

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

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

#-------------------------------------------------------------------------------
#   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:
#       --Map           - Create a MAP file
#       --NoMap         - Don't create a MAP file
#       --Scatter=file  - Names a scatter file to be used
#       --ro-base=text  - Names the ReadOnly base
#       --rw-base=text  - Names the ReadWrite base
#       --Script=file   - Additional Linker commands
#       --NoAddLibs     - No special objects and libs
#       --Heap=nn       - Create Heap definition
#
#   Output:
#       Generates makefile rules and recipes to create a program
#

sub ToolsetLD
{
    my( $name, $pArgs, $pObjs, $pLibs ) = @_;
    my $map_file;
    my $scatter_file;
    my $ro_base;
    my $rw_base;
    my @script_files;
    my $addLibs = 1;
    my $heapSize = undef;


#.. Parse arguments
#

    foreach ( @$pArgs )
    {
        if ( m~^--Map~i ) {
            $map_file = 1;

        } elsif ( m~^--NoMap~i ) {
            $map_file = 0;

        } elsif ( m~^--Scatter=(.+)~i ) {
            Src ('*', $1 );
            $scatter_file = MakeSrcResolve($1);

        } elsif ( m~^--Script=(.+)~i ) {
            Src ('*', $1 );
            push @script_files, MakeSrcResolve($1);

        } elsif ( /^--ro-base=(.+)/i ) {
            $ro_base = $1;

        } elsif ( m~^--rw-base=(.+)~i ) {
            $rw_base = $1;

        } elsif ( m~^--NoAddLibs~i ) {
            $addLibs = 0;

        } elsif ( m~^--Heap=(\d+)~i ) {
            $heapSize = 1024 * $1;
            
        } else {
            Error( "LD: unknown option $_ -- ignored\n" );
        }
    }

    #
    #   Sanity test
    #
    Error ("Can't use --scatter in conjunction with -ro-base or -rw-base")
        if ( $scatter_file && ( $ro_base || $rw_base) );

    #
    #   Determine the target output name
    #
    my $root = "\$(BINDIR)/$name";
    my $full = $root . $::exe;
    my $axf  = $root . '.axf';
    my $map  = $root . '.map';
    my $symbols  = $root . '.sym';
    my $heapRootName = "\$(OBJDIR)/heap";

    #.. 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( $axf );
    ToolsetGenerate( $symbols );

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

    #
    #   List the object files
    #   Create a definition for the objects
    #   Extend the ObjList iff we are creating the heap file
    #
    $io->Label( "Object files", $name );            # label
    $io->StartDef ("${name}_obj");
    $io->ObjList( $name, [$heapRootName], \&ToolsetObjRecipe ) if($heapSize);
    $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( "$axf : \t$dep" );                        # Dependencies
    $io->Prt( " \\\n\t$scatter_file" ) if ($scatter_file);
    $io->Prt( " \\\n\t$_" ) foreach (@script_files);
    $io->Prt( " \\\n\t\$(${name}_obj)" .
              " \\\n\t\$(${name}_lib)" );
    $io->Newline();

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


    #.. Linker command file
    #
    #       Create a variable $(name_ld) which will be the linker
    #       command line. Use previously defined values
    #
    $io->Label( "Linker commands", $name );         # label
    $io->SetTag( "${name}_ld" );                    # macro tag

    $io->Cmd( "-noscanlib");
    $io->Cmd( "-info sizes,totals");
    $io->Cmd( "-nounusedareas");
    $io->Cmd( "-nozeropad");
    $io->Cmd( "-MAP");
    $io->Cmd( "-Symbols $symbols");
    $io->Cmd( "-xref");
    $io->Cmd( "-scatter $scatter_file" ) if ($scatter_file);
    $io->Cmd( "-ro-base $ro_base" ) if defined ($ro_base);
    $io->Cmd( "-rw-base $rw_base" ) if defined ($rw_base);
    $io->Cmd( "-list $map" ) if ( $map_file );
    $io->Cmd( "-via=$_" ) foreach (@script_files);
    $io->Cmd( '$(INGEDEV_LIBS)/AppHead.o' ) if ($addLibs);                  # Fixed entries
    $io->Cmd( '$(INGEDEV_LIBS)/AppEntry.o' ) if ($addLibs);                 # Fixed entries
    $io->Cmd( "\$(subst \$(space),\\n,\$(${name}_obj))" );                  # Object file list variable
    $io->Cmd( "\$(subst \$(space),\\n,\$(${name}_lib))" );                  # Library file list variable
    $io->Newline();

    if ( $heapSize )
    {
        #
        #   Create small assember file to provide the heap
        #

        #
        #   Create rules to create the source file
        #   Done as a seperate step
        #
        #
        $io->Label( "Create Heap Source ", $name );                     # label
        $io->Prt( "${heapRootName}.$::o : \t${heapRootName}.$::s\n" );  # Dependencies
        $io->Prt( "\t\$(AS)\n\n" );
        
        #
        #   Recipe to create heap source file
        #
        $io->Prt( "${heapRootName}.s : \$(SCM_MAKEFILE)\n" );           # Dependencies
        $io->Prt("\t\$(GBE_PERL) -Mjats_runtime_arm251 -e create_heap -- --Heap=$heapSize --OutFile=\$@\n");

        #
        #   Cleanup files
        #
        ToolsetGenerate( "${heapRootName}.$::o"  );
        ToolsetGenerate( "${heapRootName}.s"  );
    }
}


########################################################################
#
#   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) = @_;

    #
    #   System libraries will have a .16l extension
    #   If the user provides a .16l extension, then don't append
    #   an extension.
    #
    $lib .= ".$::a" unless ( $lib =~ m/.16l/ );
    $io->Cmd( "${target}_lib += @(vglob2,$lib,LIB)" );
}

#.. Successful termination
1;