Subversion Repositories DevTools

Rev

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

#..
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
#
# Module name   : m16c
# Module type   : Makefile system
# Compiler(s)   : None
# Environment(s): All
#
# Description:
#       This file provides Toolset initialisation and plugin functions
#       to makelib.pl2
#
# Contents:
#
#............................................................................#

use strict;

our $s;
our $o;
our $so;
our $exe;

our @ScmToolsetArgs;
our @ScmPlatformArgs;
our $ScmToolsetVersion;
our $ScmToolsetGenerate;
our $ScmToolsetProgDependancies;
our %ScmCompilerOpts;
our %SRCS;
our $ScmBuildVersion;
our @PROGS;

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

ToolsetInit();

sub ToolsetInit
{
    my( @args ) = @ScmToolsetArgs;             # Toolset arguments
    my( $version, $product );

#.. Parse arguments
#
    Debug( "m16c(@args)\n" );

    foreach $_ ( @args ) {
        Message( "m16c: unknown toolset argument $_ -- ignored\n" );
    }

#.. Parse Platform Arguments
#
    @args = @ScmPlatformArgs;                   # Platform arguments
    foreach $_ ( @args ) {
        if (/^--product=(.*)/) {                # GBE product
            $product = $1;
        } else {
            Message( "m16c: unknown platform argument $_ -- ignored\n" );
        }
    }

#.. Standard.rul requirements
#
    $s =   'asm';           # Assembler source file
    $o =   'R30';           # Object files
    $a =   'lib';           # Library file
    $so =  undef;           # Shared library (not supported)
    $exe = '.bin';          # Program File (also .thx)

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

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

    ToolsetDefine ( "#################################################" );
    ToolsetDefine ( "# Mitsubishi m16c compiler" );
    ToolsetDefine ( "#" );

    ToolsetDefines( "m16c.def" );
    ToolsetRules  ( "m16c.rul" );
    ToolsetRules  ( "standard.rul" );

    #
    #   Other toolsets used
    #
#    PlatformDefine ("LINT_COFILE\t= m16c.lnt");
#    PlatformDefine ("LINT_PRJ_FILE\t=lint.m16c");
#    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 =
    (
    );

#
#   Allow .THX files to be process as 'cc' source files
#   Indicate that JATS is to generate objects for these files
#
AddSourceType ('.thx', '.cc' );


#
#   Install defaults
#    $ScmCompilerOpts{'xxxxx'} = "yyyyy";
#

}

##############################################################################
#   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 user has specified a Prog or Shared library, then the
    #   tools within this file will need to be able to access
    #   a few external resouces. These will be provided by packages
    #   that should exist
    #
    #
    if ( $#::TESTPROGS >= 0 || $#::PROGS >= 0 || $#::SHLIBS >= 0)
    {
        my %need = ( "fontconv.exe"     => "TOOL_FONTCONV",
                     "modcrc.exe"       => "TOOL_MODCRC",
                     "appcrc.exe"       => "TOOL_APPCRC",
                     "mcrpld.pl"        => "TOOL_MCRPLD",
                     "mcrflashend.pl"   => "TOOL_MCRFLASHEND",
                   );
        my %found = ();

        #
        #   Locate the required files
        #
        for my $program ( keys( %need ))
        {
            if ( my $path = ToolExtensionProgram( $program ) )
            {
                $found{ $need{$program} } = $path;
                delete( $need{$program} );
            }
        }

        ::Warning( "Tool program(s) required by toolset not found:",
                  sort( keys %need),
                  "Check that the mos_tools and mcr_tools packages are present" )
            if ( scalar keys %need );

        #
        #   Generate the definitions
        #

        ToolsetDefine ( "#################################################" );
        ToolsetDefine ( "#  The path to tools required to build MOS Programs" );
        ToolsetDefine ( "#" );
        for my $defn ( keys %found )
        {
            ToolsetDefine ( "$defn := $found{$defn}" );
        }
        ToolsetDefine ( "" );
    }
}


###############################################################################
#   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
{
    MakePrint( "\n\t\$(CC)\n\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\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'
#
#
#   In this toolset the source files WILL be .thx files that are to be
#   converted to "C" files and then to object files
#
#   On entry JATS has created the basic part of the recipe. The object file
#   is dependant on the source file and the makefile
#
#   This function must generate the body of the recipe
#
###############################################################################

sub ToolsetCXX
{
    my ($source, $obj, @args) = @_;
    my $name = $source;
    my $odir = "\$(OBJDIR)";
    my $tname = "$odir/${obj}";

    #
    #   Ensure that we have a .THX file
    #
    Error("Unknown file type: $source")
        unless ( $source =~ /\.thx$/i );

    #
    #   THX files are processed by:
    #       .thx    -> modcrc      ->   .bin
    #       .bin    -> fontcrc     ->   .c
    #       .c      -> compiler    ->   .r30
    #
    MakePrint( "\n\t\$(call THX2R30,$source,$tname)\n\n" );

    #
    #   Override the C source filename when building this target
    #   This is required as the C source is in the OBJ directory
    #
    MakePrint( "\$(OBJDIR)/$obj.$::o:", "\tcc_source_file=${tname}.c\n\n" );


    #
    #   Cleanup files that may be generated
    #
    ToolsetGenerate( "$tname.c" );
    ToolsetGenerate( "$tname.bin" );
    ToolsetGenerate( "$tname.thx" );
    ToolsetGenerate( "$tname.nul" );
}

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

###############################################################################
#   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, @args) = @_;
    MakePrint( "\n\t\$(AS)\n" );
    ToolsetGenerate( "\$(OBJDIR)/$obj.lst" );
}

sub ToolsetASDepend
{
}

###############################################################################
#   ToolsetAR( $name, \@args, \@objs )
#       This subroutine takes the user options and builds the rules
#       required to build the library 'name'.

#
#   Arguments:
#       --xxx                   No arguments currently defined
#
#   Output:
#       [ $(BINDIR)/name$.${a}:   .... ]
#           $(AR)
#
###############################################################################

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

    Debug("ToolsetAR");

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

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

#.. Generated files
#
    ToolsetGenerate( "\$(LIBDIR)/$name\$(GBE_TYPE).${a}.ar" );
}


###############################################################################
#   ToolsetLD( $name, \@args, \@objs, \@libraries )
#       This subroutine takes the user options and builds the rules
#       required to link the program 'name'.
#
#   The process of creating a THX files consists of:
#       1) Link .R30 object files to create a .X30 file
#       2) Process the .X30 file to create a .raw file
#       3) Use 'modcrc' to create a .thx file
#       4) Use 'modcrc' to create a .mod file (a MOS .bin file)
#
#   Note: This toolset will handle the generation of the dependancies
#         by itself. This allows complete control over the generation
#         of the dependancies. Required as the process of creating
#         a THX is complex.
#
#   Arguments:
#       --Set=Name=Value            Linker -LOC data
#       --Rel=Name                  Rel file base for MODCRC
#       --NoThx                     Suppress the creation of THX files
#       --NoPayload                 Suppress the creation of Payload files
#       --MotOnly                   Only Generate the MOT file
#                                   Forces --NoThx and --NoPayload
#
###############################################################################

sub ToolsetLD
{
    my ( $name, $pArgs, $pObjs, $pLibs ) = @_;
    my ( @slist );
    my $lib = $name;
    my %loc_list;
    my ($u_rel_file, $rel_file);
    my $no_thx;
    my $no_payload;
    my $mot_only;
    my $flash_end;
    my @builds;

#.. Parse arguments
#
    foreach $_ ( @$pArgs ) {
        if ( /^--Set=(.*)=(.*)/ ) {
            $loc_list{$1} = $2;

        } elsif (/^--Rel=(.*)/ ) {
            $u_rel_file = $1;

        } elsif (/^--NoThx/ ) {
            $no_thx = 1;

        } elsif (/^--NoPayload/ ) {
            $no_payload = 1;

        } elsif (/^--MotOnly/ ) {
            $mot_only = 1;
            $no_thx = 1;
            $no_payload = 1;
            
        } elsif (/^--FlashEnd=(.*)/ ) {
            $flash_end = $1;
            
        } else {
            Message( "m16c LD: unknown option $_ -- ignored\n" );
        }
    }

    #
    #   Post processing
    #
    if ( $u_rel_file )
    {
        #
        #   Locate the true path of the provided REL file
        #   If it is a generate file it will be in the SRCS hash
        #   Otherwise the user will have to use Src to locate the file
        #
        $rel_file = MakeSrcResolve ( $u_rel_file );
    }

    #
    #   Prepare version information
    #
    my @ver_data = split( /\./, $ScmBuildVersion);

    #
    #   Create a printer tool instance
    #
    my $io = ToolsetPrinter::New();

    #
    #   Create the flash size information for this linker Target
    #
    $io->Label( "Flash Boundary Checking", $name );
    if ( $flash_end )
    {
        $io->Prt( "${name}_FlashEnd = $flash_end\n" );
    }
    else
    {
        $io->Prt( "${name}_FlashEnd = 0\n" );
    }
    $io->Newline();

    unless ( $no_payload )
    {
        ####################################################################
        #
        #   Build the .payload file from the .bin file
        #
        my $pl_file = "\$(BINDIR)/${lib}_$ver_data[0].$ver_data[1].$ver_data[2].payload";
        $io->Label( "Payload Module", $name );
        $io->Prt( "$pl_file :" .
                  "\\\n\t\t\$(BINDIR)/$lib.bin ".
                  "\n\t\t\$(call MCRPLD,$ver_data[0].$ver_data[1].$ver_data[2])\n"
                );
        $io->Newline();

        #
        #   Register generated file for cleanup
        #
        ToolsetGenerate( $pl_file );

        #
        #   Specify the files to be packaged as part of the shared library
        #
        PackageProgAddFiles( $name, $pl_file );
        ProgAddExtra( $name, $pl_file );
        push @builds, $pl_file;
    }


    unless ( $no_thx )
    {
        ####################################################################
        #
        #   Build the .thx file from the .raw file
        #
        my $rel_mod = "\$(BINDIR)/$name.rel";
        $io->Label( "THX Module", $name );
        $io->Prt( "\$(BINDIR)/$lib.thx :" .
                  "\\\n\t\t\$(BINDIR)/$lib.raw ".
                  "\\\n\t\t$rel_mod ".
                  "\n\t\t\$(call MODCRC,$rel_mod)\n"
                );
        $io->Newline();

        #
        #   Register generated file for cleanup
        #   The MODCRC process generates a .bak file. Ensure that it gets removed
        #
        ToolsetGenerate( "\$(BINDIR)/$lib.thx" );
        ToolsetGenerate( "\$(BINDIR)/$lib.bak" );
        ToolsetGenerate( "\$(BINDIR)/$lib.mod" );

        #
        #   Specify the files to be packaged as part of the shared library
        #
        PackageProgAddFiles( $name, "\$(BINDIR)/$lib.thx" );
        PackageProgAddFiles( $name, "\$(BINDIR)/$lib.mod" );
        ProgAddExtra( $name, "\$(BINDIR)/$lib.thx" );
        ProgAddExtra( $name, "\$(BINDIR)/$lib.mod" );
        push @builds, "\$(BINDIR)/$lib.thx";
        push @builds, "\$(BINDIR)/$lib.mod";

        #
        #   Generate the .rel files needed by MODCRC in the generation
        #   of the .THX file
        #
        #   Need to massage the version number to be a decimal representation
        #   of a BCD number. Required to interwork with Mug Files
        #   The version number consists of 4 BCD chacaters
        #       The  most significant 2 are the major number 0-99
        #       The least significant 2 are the minor number 0-99
        #
        #   Can't do this at 'make time'
        #
        sub convertBcdDigit
        {
            my ($num, $shift) = @_;
            return ($num % 10) << $shift;
        }
        
        if ( $ver_data[1] > 99 || $ver_data[0] > 99 )
        {
            Error ("Cannot convert the package version number to required format",
                   "Major and Minor numbers MUST be less that 99",
                   "Major: $ver_data[0], Minor: $ver_data[1]");
        }
        my $ver = convertBcdDigit( $ver_data[1]     , 0 )
                + convertBcdDigit( $ver_data[1] / 10, 4)
                + convertBcdDigit( $ver_data[0]     , 8 )
                + convertBcdDigit( $ver_data[0] / 10, 12 );
        

        $io->Prt( "$rel_mod :" .
                  "\\\n\t\t$rel_file ".
                  "\\\n\t\t\$(GBE_PLATFORM).mk " .
                  "\n\t\t\$(XX_PRE)\$(echo) > $rel_mod \"version=$ver\"\n" );
        $io->Prt ( "\t\t\$(XX_PRE)\$(grep) < $rel_file >> $rel_mod -v \"^version\"\n" ) if($rel_file);
        $io->Newline();
        ToolsetGenerate( $rel_mod );
    }

    unless ( $mot_only )
    {
        ####################################################################
        #
        #   Build the .raw file from the .X30 file
        #   Build a .bin file in the process that has a version number embedded
        #   in the name of the file
        #
        my $bin = $lib . "_$ver_data[0].$ver_data[1].$ver_data[2]";
        $bin = "\$(BINDIR)/$bin.bin";

        $io->Label( "Raw Binary Image", $name );
        $io->Prt( "\$(BINDIR)/$lib.raw \\\n" .
                  "\$(BINDIR)/$lib.bin \\\n" .
                  "$bin \\\n" .
                  "\$(BINDIR)/$lib.mot:" .
                  "\\\n\t\t\$(BINDIR)/$lib.X30 ".
                  "\n\t\t\$(call LMC,$bin)\n"
                );
        $io->Newline();
    
        PackageProgAddFiles( $name, $bin );
        ProgAddExtra( $name, $bin );
        push @builds, $bin;

        PackageProgAddFiles( $name, "\$(BINDIR)/$lib.bin" );
        ProgAddExtra($name, "\$(BINDIR)/$lib.bin" );
        push @builds, "\$(BINDIR)/$lib.bin";

        #
        #   Register generated file for cleanup
        #
        ToolsetGenerate( "\$(BINDIR)/$lib.mot" );
        ToolsetGenerate( "\$(BINDIR)/$lib.bin" );
        ToolsetGenerate( $bin );
        ToolsetGenerate( "\$(BINDIR)/$lib.raw" );

    }
    else
    {
        ####################################################################
        #
        #   Build the .mot file from the .X30 file
        #   Build a .mot file that has a version number embedded in the name of the file
        #
        my $bin = $lib . "_$ver_data[0].$ver_data[1].$ver_data[2]";
        $bin = "\$(BINDIR)/$bin.mot";

        $io->Label( "MOT Image", $name );
        $io->Prt( "\$(BINDIR)/$lib.mot \\\n" .
                  "$bin:" .
                  "\\\n\t\t\$(BINDIR)/$lib.X30 ".
                  "\n\t\t\$(call LMC_MOT,$bin)\n"
                );
        $io->Newline();
    
        PackageProgAddFiles( $name, $bin );
        ProgAddExtra( $name, $bin );
        push @builds, $bin;

        PackageProgAddFiles( $name, "\$(BINDIR)/$lib.mot" );
        ProgAddExtra($name, "\$(BINDIR)/$lib.mot" );
        push @builds, "\$(BINDIR)/$lib.mot";

        #
        #   Register generated file for cleanup
        #
        ToolsetGenerate( "\$(BINDIR)/$lib.mot" );
        ToolsetGenerate( $bin );
    }

    ####################################################################
    #
    #   Build the .X30 file from the .R30 object files
    #
    my $dep = $io->SetLdTarget( $lib );

    $io->Label( "Link Object Files", $name );
    my $Xname = "\$(BINDIR)/$lib";
    my $Tname = "$Xname.X30";

    $io->Prt( "$Tname:\tSHBASE=${lib}\n" );
    $io->Prt( "$Tname:\tSHNAME=${lib}\n" );
    $io->Entry( "$Tname :\t", "", "\\\n\t\t", ".$::o ", @$pObjs );
    $io->Prt( "\\\n\t\t\$(SCM_MAKEFILE) " );
    $io->Prt( "\\\n\t\t$dep " );
    $io->Prt( "\n\t\$(LD)\n" );
    $io->Newline();

    #
    #   Add the MAP file to the program package
    #
    PackageProgAddFiles( $name, "\$(BINDIR)/${name}.map" , 'Class=map' );
    
    #
    #   Register generated file for cleanup
    #
    ToolsetGenerate( "$Xname.X30" );
    ToolsetGenerate( "$Xname.map" );

    ####################################################################
    #
    #   Build the linker command file
    #
    #   Now the fun part... piecing together a variable ${name}_ld
    #   which ends up in the command file.
    #
    $io->Label( "Linker commands", $name );     # label
    $io->SetTag( "${lib}_ld" );                 # command tag

    $io->Cmd( "-O \$(subst /,\\,$Xname.X30)" );
    $io->Cmd( "-G" );
    $io->Cmd( "-MS" );
    $io->Cmd( "-." );

    #
    #   User specified locations
    #
    for (keys %loc_list ) {
        $io->Cmd( "-LOC $_=$loc_list{$_}" );
    }

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

    #
    #   System libraries last
    #
    $io->Cmd( "-L \$(LIB30)\\\\nc30lib.lib" );


    $io->Newline();
    ToolsetGenerate( "$Xname.ld" );

    ####################################################################
    #
    #.. Dependency link,
    #   Create a linker dependency file
    #   This will be used to generate associations between the .X30 file
    #   and libraries used to create the .X30 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, "$Xname.X30" );
    $io->LDDEPEND();

    #
    #   The Program that 'should' be created by this function does not always
    #   get produced. The name MUST be retained, but it is a PHONY.
    #   Create a recipe to build the bits we really need
    #
    my %builds;
    $builds{$_} = 1 foreach @builds;
    my $prog_target = "\$(BINDIR)/$name$exe";
    unless ( exists ($builds{$prog_target} ))
    {
        #
        $io->Label( "Phony Program", $name );
        $io->PrtLn( ".PHONY: $prog_target" );
        $io->Entry( "$prog_target :\t", "", "\\\n\t\t", "", @builds );
        $io->Newline();
    }

}

########################################################################
#
#   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("\$(subst /,\\\\,$obj.$::o)");
}

########################################################################
#
#   Generate a linker/depend library recipe.  This is a helper function
#   used within this toolset.
#
#   Arguments:
#       $io         I/O stream
#       $target     Name of the target
#       $lib        Library specification
#       $dp         If building a depend list, the full target name.
#
########################################################################

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

    if ( !defined($dp) ) {                      # linker
        $io->Cmd("-L @(vpath2,$lib.$::a,M16C_LIB)" );

    } else {                                    # depend
        $io->Cmd( "$dp:\t@(vlib2,$lib.$::a,M16C_LIB)" );
    }
}


1;