Rev 287 | Rev 321 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
# -*- mode: perl; tabs: 8; indent-width: 4; show-tabs: yes; -*-## Module name : GCC# Module type : Makefile system# Compiler(s) : ANSI C# Environment(s): GCC## Description:# GCC C/C++ toolset##............................................................................#use strict;use warnings;############################################################################### Configuration information# Cross reference from CrossCompiler Alias to actual paths# Structure:# Hash reference: Array of toolchain information# Root of compiler# Path to gcc# Path to ar##my %ToolsetConfig = (## Preferred version of the embedded toolchain#'i386-unknown-linux-gnu' => ['/opt/crosstool/gcc-4.1.1-glibc-2.5/i586-unknown-linux-gnu','bin/i586-unknown-linux-gnu-gcc' ],'arm-9tdmi-linux-gnu' => ['/opt/crosstool/gcc-4.1.1-glibc-2.5/arm-9tdmi-linux-gnu','bin/arm-9tdmi-linux-gnu-gcc' ],'powerpc-603e-linux-gnu' => ['/opt/crosstool/gcc-4.1.1-glibc-2.5/powerpc-603e-linux-gnu','bin/powerpc-603e-linux-gnu-gcc'],## Old (not to be used) version of the embedded toolchain# This was depricated in favor of gcc-4.1.1-glibc-2.5# It is not possible to reproduce old packages using the old compiler# This is a known issue#'i386-unknown-linux-gnu.glibc-2.3.2' => ['/opt/crosstool/gcc-4.1.0-glibc-2.3.2/i386-unknown-linux-gnu','bin/i386-unknown-linux-gnu-gcc' ],'arm-9tdmi-linux-gnu.glibc-2.3.2' => ['/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu','bin/arm-9tdmi-linux-gnu-gcc' ],## Not too sure where this is used#'armv4l-unknown-linux-gcc' => [ '/opt/host/armv4l','bin/armv4l-unknown-linux-gcc' ],## The compiler for the current local machine#'i386-unknown-linux-gcc' => [ '/opt/host/i386','bin/i386-unknown-linux-gcc' ],);## Cross reference from GCCTarget to GBE_MACHTYPE for which it can# build using the 'native gcc'. This is NOT the preferred mode of operation# as the compiler is not as controlled as the cross compilers.#my %NativeCompilers = ('Linux i386' => 'linux_i386',);############################################################################### ToolsetInit()# Runtime initialisation###############################################################################ToolsetInit();sub ToolsetInit{my( $GCCTarget, @GCCToolchain, $GCCRoot, $GCCBin, $GCCAr );my( $arg_alias, $tools_found );#.. Toolset configuration#$::ScmToolsetVersion = "1.0.0"; # our version$::ScmToolsetGenerate = 0; # GEN generate optional$::ScmToolsetCompilerPath = 1; # Exports Compiler path to makefile via SCM_COMPILERPATH$::ScmToolsetProgDependancies = 0; # handle Prog dependancies myself#.. Standard.rul requirements#$::s = "asm";$::o = "o";$::so = "so";$::a = "a";$::exe = "";#.. Parse arguments#foreach $_ ( @::ScmToolsetArgs ) {if (/^--Target=(.*)/) { # OS Version$GCCTarget = "$1";} elsif (/^--CrossAlias=(.*)/) { # CrossCompiler target-alias$arg_alias = $1;} else {Message( "gcc toolset: unknown option $_ -- ignored\n" );}}foreach $_ ( @::ScmPlatformArgs ) {if (/^--product=(.*)/) { # GBE product} else {Message( "gcc toolset: unknown platform argument $_ -- ignored\n" );}}Error ("TOOLSET/gcc - Target undefined" )unless ($GCCTarget);#.. Cross compile support## Toolchain=root,[bin]#if ( $arg_alias ){if ( exists $ToolsetConfig{ $arg_alias } ){@GCCToolchain = @{$ToolsetConfig{ $arg_alias }};$tools_found = (-d $GCCToolchain[0]);Warning ("gcc toolset: CrossPlatform toolchain not found for: $arg_alias","Path: $GCCToolchain[0]" ) unless $tools_found;}else{Error("gcc toolset: CrossPlatform Alias not configured: $arg_alias");}}## If no Cross compiler toolchain is found (preferred method), then attempt# to match a native compiler. Only known targets allow a native build#unless ( $tools_found ){if ( exists ( $NativeCompilers{$GCCTarget} )){if ( $NativeCompilers{$GCCTarget} eq $::GBE_MACHTYPE ){$tools_found = 1;@GCCToolchain = ();}}}## Must have a toolset by now, either a cross compiler or Native#Error ("gcc toolset: Toolchain not found for: $GCCTarget" )unless ( $tools_found );if ( @GCCToolchain ){## Parse GCCToolchain. Potentially three parts# [0] - GCCRoot - Location to find the effective /usr/include directory# [1] - GCCBin - Path to the gcc executable# If relative, then its relative to GCCRoot# [2] - GCCAr - Path to the ar executable# If relative, then its relative to GCCRoot# If not defined then its the same as GCCBin with gcc replaced with ar#$GCCRoot = $GCCToolchain[0];# GCC_CC definition#if ( $GCCToolchain[1] ){ # user specificationif ( substr($GCCToolchain[1],0,1) ne "/") {$GCCBin = $GCCToolchain[0].'/'.$GCCToolchain[1];} else {$GCCBin = $GCCToolchain[1]; # abs path}}else{ # default$GCCBin = $GCCToolchain[0] . '/bin/gcc';}# GCC_AR definition#if ( defined($GCCToolchain[2]) && $GCCToolchain[2] ){ # user specificationif ( substr($GCCToolchain[2],0,1) ne "/") {$GCCAr = $GCCToolchain[0].'/'.$GCCToolchain[2];} else {$GCCAr = $GCCToolchain[2]; # abs path}}else{ # default, base on GCCBin$GCCAr = substr($GCCBin,0,length($GCCBin)-3)."ar";}}else{$GCCRoot = "/usr";$GCCBin = "gcc";$GCCAr = "ar";}#.. Define GCC environment#PlatformDefine( "################################################## GCC toolchain definitions##..");PlatformDefine( "GCC_TARGET\t". ":=$GCCTarget" );PlatformDefine( "GCC_ROOT\t". ":=$GCCRoot" );PlatformDefine( "GCC_CC\t\t". ":=$GCCBin" );PlatformDefine( "GCC_AR\t\t". ":=$GCCAr" );PlatformDefine( "" );## Required since this toolset advertises: ScmToolsetCompilerPath#PlatformDefine( "SCM_COMPILERPATH\t\t". ":=$GCCBin" );#.. Piece the world together#Init( "gcc" );ToolsetDefines( "gcc.def" );ToolsetRules( "gcc.rul" );ToolsetRules( "standard.rul" );# 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#'staticprogs' => { 'STATIC_PROGS' , '1' }, # Progams link staticlly'no_staticprogs' => { 'STATIC_PROGS' , undef }, # Default);## Set default options#$::ScmCompilerOpts{'STATIC_PROGS'} = undef;}################################################################################ 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, $file ) = "";foreach $_ ( @$pArgs ) {if (/--Shared$/) { # Building a 'shared' object$cflags = "$cflags \$(SHCFLAGS)";} else {Message( "CC: unknown option $_ -- ignored\n" );}}MakePrint( "\n\t\$(CC)\n" );if ( $cflags ){ # object specific CFLAGSMakePadded( 4, "\$(OBJDIR)/$obj.$::o:" );MakePrint( "\tCFLAGS +=$cflags\n" );}$file = StripExt( $obj ); # Metric working fileToolsetGenerate( "\$(OBJDIR)/$file.met" );}################################################################################ 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{my( $source, $obj, $pArgs ) = @_;my( $cflags, $file ) = "";foreach $_ ( @$pArgs ) {if (/--Shared$/) { # Building a 'shared' object$cflags = "$cflags \$(SHCXXFLAGS)";} else {Message( "CXX: unknown option $_ -- ignored\n" );}}MakePrint( "\n\t\$(CXX)\n" );if ( $cflags ){ # object specific CFLAGSMakePadded( 4, "\$(OBJDIR)/$obj.$::o:" );MakePrint( "\tCXXFLAGS +=$cflags\n" );}$file = StripExt( $obj ); # Metric working fileToolsetGenerate( "\$(OBJDIR)/$file.met" );}################################################################################ 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{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:# n/a## Output:# $(BINDIR)/name$.${a}: .... ]# $(AR)## name_ld += ... Linker command file# :## name_dp += ... Dependency list# :################################################################################sub ToolsetAR{my( $name, $pArgs, $pObjs ) = @_;#.. Parse arguments#foreach $_ ( @$pArgs ){Message( "AR: unknown option $_ -- ignored\n" );}#.. Target#MakePrint( "#.. Library ($name)\n\n" ); # labelMakeEntry( "\$(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" );}################################################################################ 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:# n/a## Output:# $(LIBDIR)/name: $(LIBDIR)/shared# ln -s $shared $name## $(LIBDIR)/name.dep: $(GBE_OBJDIR)# $(LIBDIR)/name.dep: $(GBE_LIBDIR)# $(LIBDIR)/name.dep: $(GBE_PLATFORM).mk# $(SHLDDEPEND)## $(LIBDIR)/shared: SHNAME=name# $(LIBDIR)/shared: SHBASE=base# $(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( $shared, $def, $def_pref, $multi_scan );#.. Parse arguments#foreach $_ ( @$pArgs ){if (/^--Def=(.*?)(\,(.*))?$/) { # Library definition## Locate the Def file.# If it is a generate file so it will be in the SRCS hash# Otherwise the user will have to use Src to locate the file#$def = MakeSrcResolve($1);$def_pref = '';if ( $1 =~ m~\.def$~ ) {$def_pref = '--version-script='; # Old def file}} elsif ( /^--MultiScan/i ) {$multi_scan = 1;} elsif ( /^--NoMultiScan/i ) {$multi_scan = 0;} else {Message( "SHLD: unknown option $_ -- ignored\n" );}}#.. Full name of shared library#$shared = "$name\$(GBE_TYPE).$::so.$ver{ $name }";#.. Install and package the shared libraries that are generated#PackageShlibAddFiles( $name, "\$(LIBDIR)/${name}\$(GBE_TYPE).$::so" );PackageShlibAddFiles( $name, "\$(LIBDIR)/$shared" );#.. Cleanup rules## dep Dependency file# map Map file# ln Link from LIBDIR to BINDIR#ToolsetGenerate( "\$(LIBDIR)/${name}.dep" );ToolsetGenerate( "\$(LIBDIR)/${name}.map" );ToolsetGenerate( "\$(LIBDIR)/${shared}" );ToolsetGenerate( "\$(BINDIR)/${shared}" );#.. Build rules## name Base name# shared Library name, includes GBE_TYPE specification#my ($io) = ToolsetPrinter::New();$io->Label( "Shared library", $name );$io->Prt( "\$(LIBDIR)/${name}\$(GBE_TYPE).$::so:\t\\\n" ."\t\t\$(GBE_BINDIR)\\\n" ."\t\t\$(LIBDIR)/${shared}\n" ."\t\@(rm -f \$@; ln -s ./$shared \$@)\n" ."\t\@(rm -f \$(BINDIR)/$shared; ln -s ../\$(LIBDIR)/$shared \$(BINDIR)/$shared)\n\n" );$io->SHLDDEPEND($name, $name, $shared); # std SHLDDEPEND rules$io->Prt( "\$(LIBDIR)/${shared}:\tSHBASE=${name}\n" );$io->Prt( "\$(LIBDIR)/${shared}:\tSHNAME=${shared}\n" );$io->Entry( "\$(LIBDIR)/${shared}:\t", "", "\\\n\t\t", ".$::o", @$pObjs );$io->Prt( "\\\n\t\t$def" ) if($def);$io->Prt( "\\\n\t\t\$(LIBDIR)/${name}.dep\n" );$io->Prt( "\t\$(SHLD)\n\n" );#.. Linker command file## Now the fun part... piecing together a variable $(name_shld)# which ends up in the command file.#$io->SetTag( "${name}_shld" ); # command tag$io->SetTerm( "\n" );$io->Label( "Linker commands", $name ); # label# object list$io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );ToolsetLibStd( $pLibs ); # push standard libraries$io->Cmd( "-Wl,$def_pref$def" ) if ($def);$io->Cmd( "-Wl,--start-group" ) if ($multi_scan);$io->LibList( $name, $pLibs, \&ToolsetLibRecipe );$io->Cmd( "-Wl,--end-group" ) if ($multi_scan);$io->Newline();#.. Dependency link,## Now piece together a variable $(name_dp) which ends up in# the command file building the application dependency list.#$io->SetTag( "${name}_shdp" ); # command tag$io->SetTerm();$io->DepRules( $name, $pLibs, # library depends rules\&ToolsetLibRecipe, "$shared" );$io->Newline();}################################################################################ Function : ToolsetLD## Description : Takes the user options and builds the rules required to# link the program 'name'.## Inputs : $name - base name of the program# $pArgs - Ref to program arguments# $pObjs - Ref to program objects# $pLibs - Ref to program library list## Returns : Nothing## Output: : Rules and recipes to create a program# Create program rules and recipes# Create linker input script# Create library dependency list# Include library dependency information#sub ToolsetLD{my( $name, $pArgs, $pObjs, $pLibs ) = @_;my $static = $::ScmCompilerOpts{'STATIC_PROGS'};my $multi_scan;#.. Parse arguments#foreach $_ ( @$pArgs ){if ( m/^--Static$/ ) {$static = 1;} elsif ( m/^--Shared/ ) {$static = 0;} elsif ( /^--MultiScan/i ) {$multi_scan = 1;} elsif ( /^--NoMultiScan/i ) {$multi_scan = 0;} else {Message( "LD: unknown option $_ -- ignored\n" );}}#.. Names of programs and components#my $base = "\$(BINDIR)/${name}";my $full = $base . $::exe;my $dep = $base . '.dep';my $map = $base . '.map';my $ld = $base . '.ld';#.. Cleanup rules#ToolsetGenerate( $ld );ToolsetGenerate( $dep );ToolsetGenerate( $map );#.. Build rules#my ($io) = ToolsetPrinter::New();$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->Cmd( "-static" ) if ($static); # Link as a static program# object list$io->ObjList( $name, $pObjs, \&ToolsetObjRecipe );ToolsetLibStd( $pLibs ); # push standard libraries# library list$io->Cmd( "-Wl,--start-group" ) if ($multi_scan);$io->LibList( $name, $pLibs, \&ToolsetLibRecipe );$io->Cmd( "-Wl,--end-group" ) if ($multi_scan);$io->Newline();#.. Library dependency information# Rules to include a .dep file when required#$io->LDDEPEND( $name );#.. Dependency link,## Now piece together a variable $(name_dp) which ends up in# the command file building the application dependency list.#$io->SetTag( "${name}_dp" ); # macro tag$io->SetTerm();$io->DepRules( $name, $pLibs, # library depends rules\&ToolsetLibRecipe, $base );$io->Newline();#.. 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,GCC_LIB)" );}}#.. Successful termination1;