Rev 7040 | Rev 7547 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
######################################################################### COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.## Module name : GCC.PL# Module type : JATS Utility# Compiler(s) : Perl# Environment(s): jats## Description : GCC C/C++ toolset##......................................................................#use strict;use warnings;# Global variablesour $ScmPlatform;our $ScmNoToolsTest;# Misc variablesmy $UseGcov = 0;my $UseProfile = 0;my $LcovExplicitBranch = '';my $UseCppcheck = 0;my $GCCRPath;my @ldFixups;############################################################################### Configuration information# Cross reference from CrossCompiler Alias to actual paths# Structure:# Hash reference: Array of toolchain information# Mandatory# ROOT => Root of compiler# BASE => Base for binaries# Optional# CC_OPTS => Additonal Compiler options# CC_OPTSP => Production Compiler options# CC_OPTSD => Debug Compiler options# CXX_OPTS => Additional C++ Options# LDFLAGS => Linker flags# UNCONTROLLED => Boolean to create warning# DEPRECATED => Boolean to create warning# DISCONTINUED => Boolean to create error and not build anything# PACKAGE_ARCH => Packageing architecture# VERSION => Version reported by GCC# MACHINE => Machine reported by GCC# RPATH => Relative Path to compiler installed runtime# Absolute or Relative# COMPILER_OPTIONS => Toolset specific compiler initial options# This is a comma seperated listmy %ToolsetConfig = ('i386-unknown-linux-gnu' => {ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/i586-unknown-linux-gnu',BASE => 'bin/i586-unknown-linux-gnu-',VERSION => '4.1.1',MACHINE => 'i586-unknown-linux-gnu'},'arm-9tdmi-linux-gnu' => {ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/arm-9tdmi-linux-gnu',BASE => 'bin/arm-9tdmi-linux-gnu-',VERSION => '4.1.1',MACHINE => 'arm-9tdmi-linux-gnu'},'powerpc-603e-linux-gnu' => {ROOT => '/opt/crosstool/gcc-4.1.1-glibc-2.5/powerpc-603e-linux-gnu',BASE => 'bin/powerpc-603e-linux-gnu-',VERSION => '4.1.1',MACHINE => 'powerpc-603e-linux-gnu'},'arm-926ejs-linux-gnueabi' => {ROOT => '/opt/crosstool/gcc-4.4.3-glibc-2.9/arm-926ejs-linux-gnueabi',BASE => 'bin/arm-926ejs-linux-gnueabi-',CC_OPTS => '-Wno-psabi',VERSION => '4.4.3',MACHINE => 'arm-926ejs-linux-gnueabi'},'arm-926ejs-linux-gnueabi-v2' => {ROOT => '/opt/crosstool/gcc-5.2.0-glibc-2.17/arm-926ejs-linux-gnueabi',BASE => 'bin/arm-926ejs-linux-gnueabi-',CC_OPTS => '-Wno-psabi',CXX_OPTS => '-std=gnu++11',VERSION => '5.2.0',MACHINE => 'arm-926ejs-linux-gnueabi'},'powerpc-603e-linux-gnu-v2' => {ROOT => '/opt/crosstool/gcc-5.2.0-glibc-2.17/powerpc-603e-linux-gnu',BASE => 'bin/powerpc-603e-linux-gnu-',CXX_OPTS => '-std=gnu++11',VERSION => '5.2.0',MACHINE => 'powerpc-603e-linux-gnu'},'i686-linux-gnu' => {ROOT => '/usr',BASE => 'bin/',PACKAGE_ARCH => 'i386',VERSION => '4.6',MACHINE => 'i686-linux-gnu'},'i686-vix_ubuntu12_c11-linux-gnu' => {ROOT => '/opt/crosstool/gcc-5.2.0-glibc-2.17/i686-vix_ubuntu12_c11-linux-gnu',BASE => 'bin/i686-vix_ubuntu12_c11-linux-gnu-',PACKAGE_ARCH => 'i386',CXX_OPTS => '-std=gnu++11',VERSION => '5.2.0',MACHINE => 'i686-vix_ubuntu12_c11-linux-gnu',RPATH => '/lib/i686-vix_ubuntu12_c11-linux-gnu',},'arm-iwmmxt-linux-gnueabi' => {ROOT => '/opt/marvel',BASE => 'bin/arm-iwmmxt-linux-gnueabi-',VERSION => '4.2.4',MACHINE => 'arm-iwmmxt-linux-gnueabi'},'arm-unknown-linux-gnueabi-sk20-4.1.1.0' => {ROOT => '/opt/arm-unknown-linux-gnueabi-sk20-4.1.1.0',BASE => 'bin/arm-unknown-linux-gnueabi-',VERSION => '4.8.2',MACHINE => 'arm-unknown-linux-gnueabi'},'gmx-sdk-imx6-toolchain-5.0.0.0' => {ROOT => '/opt/gmx-sdk-imx6-toolchain-5.0.0.0',BASE => 'bin/arm-unknown-linux-gnueabi-',VERSION => '4.9.1',MACHINE => 'arm-unknown-linux-gnueabi',COMPILER_OPTIONS => 'pic,brokenldscripts',},# Ubuntu14'x86_64-linux-gnu' => {ROOT => '/usr',BASE => 'bin/',PACKAGE_ARCH => 'amd64',CXX_OPTS => '-std=gnu++11',VERSION => '4.8',MACHINE => 'x86_64-linux-gnu',COMPILER_OPTIONS => 'pic' # Always create PIC},# Ubuntu16'x86_64-linux-gnu-5.4' => {ROOT => '/usr',BASE => 'bin/',PACKAGE_ARCH => 'amd64',CXX_OPTS => '-std=gnu++11',VERSION => '5.4.0',MACHINE => 'x86_64-linux-gnu',COMPILER_OPTIONS => 'pic' # Always create PIC},'x86_64-redhat-linux-4.8.5' => {ROOT => '/usr',BASE => 'bin/',PACKAGE_ARCH => 'x86_64',CXX_OPTS => '-std=gnu++11',VERSION => '4.8.5',MACHINE => 'x86_64-redhat-linux',COMPILER_OPTIONS => 'pic' # Always create PIC},# STIB Parkeon'arm-linux-gnueabi-4.6.3' => {ROOT => '/opt/parkeon-arm-linux-gnueabi-4.6',BASE => 'bin/arm-linux-gnueabi-',PACKAGE_ARCH => 'armel',#CXX_OPTS => '',VERSION => '4.6.3',MACHINE => 'arm-linux-gnueabi',COMPILER_OPTIONS => 'pic' # Always create PIC},## Old (not to be used) version of the embedded toolchain# This was deprecated 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' => {ROOT => '/opt/crosstool/gcc-4.1.0-glibc-2.3.2/i386-unknown-linux-gnu',BASE => 'bin/i386-unknown-linux-gnu-'},'arm-9tdmi-linux-gnu.glibc-2.3.2' => {ROOT => '/opt/crosstool/gcc-4.1.0-glibc-2.3.2/arm-9tdmi-linux-gnu',BASE => 'bin/arm-9tdmi-linux-gnu-'},## Not too sure where this is used#'armv4l-unknown-linux-gcc' => {ROOT => '/opt/host/armv4l',BASE => 'bin/armv4l-unknown-linux-'},## The compiler for the current local machine#'i386-unknown-linux-gcc' => {ROOT => '/usr',BASE => 'bin/',UNCONTROLLED => 1,PACKAGE_ARCH => 'i386',},);## 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, $GCCObjCopy, $GCCGcovTool );my( $GCCFlags, $GCCFlagsP, $GCCFlagsD, $LDFlags );my( $GCCXXFlags );my( $PkgArch);my( $arg_alias, $tools_found, $compiler_tool );#.. Toolset configuration# Also $::ScmToolsetProperties{}#$::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$::ScmToolsetSoName = 1; # Shared library supports SoName#.. 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;} elsif (/^--UseGcov/) { # Compile for code coverage$UseGcov = 1;} elsif (/^--UseProfile/) { # Compile for profiling$UseProfile = 1;} elsif (/^--LcovExplicitBranch/) { # Version of lcov requires explicit branch coverage$LcovExplicitBranch = ' --rc lcov_branch_coverage=1';} elsif (/^--UseCppcheck/) { # Use cppcheck as the lint tool$UseCppcheck = 1;} elsif (/^--CompilerTool=(.*)/) { # CrossCompiler located in package$compiler_tool = $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);## If the toolset is not required, then do not process any futher# We may not find the compiler#returnif ($ScmNoToolsTest);#.. Cross compile support# Compiler provided in package, rather than install on machine#if ( $compiler_tool ){## The GCC toolset will handle a compiler provided within a package# Initial requirement was for ANDROID NDKs where the compiler is# a part of the NDK and will change.## Compilers in packages will have a file in gbe/COMPILERS/<compiler_tool># that contains data specifically designed for this toolset#Verbose("Locate compiler in package: $compiler_tool");my @toolList;my $toolPath;my $toolPkg;for my $entry (@{$::ScmBuildPkgRules{$ScmPlatform} }){my $tpath = join('/', $entry->{ROOT}, 'gbe', 'COMPILERS' , $compiler_tool);if ( -f $tpath ){push @toolList, $entry->{NAME};$toolPath = $tpath;$toolPkg = $entry;}}Error ("Multiple packages provide required compiler:", @toolList)if ( scalar(@toolList) > 1 );Error ("Required compiler not found in any package", "Compiler: $compiler_tool")unless ( scalar(@toolList) == 1 );## Process the compiler info file# Rip out the data and create a hash of item/values# File format:# '#' is a line comment# item=value#my %data;open (my $DATA, '<', $toolPath ) || Error("Cannot open compiler datafile. $!", "File: $toolPath");while ( <$DATA> ){$_ =~ s~\s+$~~;next if ( m~^#~ );m~(.*?)\s*=\s*(.*)~;$data{$1} = $2;}close $DATA;## Force this compilers data into the ToolsetConfig hash#$arg_alias = $compiler_tool;%ToolsetConfig = ();$ToolsetConfig{$arg_alias}{ROOT} = join('/', $toolPkg->{ROOT}, $data{ROOT} );$ToolsetConfig{$arg_alias}{BASE} = $data{BASE} . '-';$ToolsetConfig{$arg_alias}{CC_OPTS} = $data{CFLAGS};$ToolsetConfig{$arg_alias}{CC_OPTSP} = $data{CFLAGSP};$ToolsetConfig{$arg_alias}{CC_OPTSD} = $data{CFLAGSD};$ToolsetConfig{$arg_alias}{CXX_OPTS} = $data{CXXFLAGS};$ToolsetConfig{$arg_alias}{LDFLAGS} = $data{LDFLAGS};$ToolsetConfig{$arg_alias}{VERSION} = $data{VERSION};$ToolsetConfig{$arg_alias}{MACHINE} = $data{MACHINE};$ToolsetConfig{$arg_alias}{COMPILER_OPTIONS} = $data{COMPILER_OPTIONS};$ToolsetConfig{$arg_alias}{RAPTH} = $data{RPATH};$ToolsetConfig{$arg_alias}{DEPRECATED} = $data{DEPRECATED};$ToolsetConfig{$arg_alias}{DISCONTINUED} = $data{DISCONTINUED};}#.. Cross compile support## Toolchain=root,[bin]#if ( $arg_alias ){if ( exists $ToolsetConfig{ $arg_alias } ){$GCCToolchain = $ToolsetConfig{ $arg_alias };my $testCompilerPath = $GCCToolchain->{ROOT} . '/' . $GCCToolchain->{BASE} . 'gcc';$tools_found = (-d $GCCToolchain->{ROOT}) && ( -f $testCompilerPath);Warning ("gcc toolset: CrossPlatform toolchain not found for: $arg_alias","Path : $GCCToolchain->{ROOT}" ,"Compiler: $testCompilerPath ") unless $tools_found;}else{Error("gcc toolset: CrossPlatform Alias not configured: $arg_alias");}Warning ("Uncontrolled toolchain used: $arg_alias")if ( exists($GCCToolchain->{UNCONTROLLED}) && $GCCToolchain->{UNCONTROLLED} );Warning ("Deprecated toolchain used: $arg_alias")if ( exists($GCCToolchain->{DEPRECATED}) && $GCCToolchain->{DEPRECATED} );Error ("Discontinued toolchain used: $arg_alias")if ( exists($GCCToolchain->{DISCONTINUED}) && $GCCToolchain->{DISCONTINUED} );}## 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 = undef;}}}## Must have a toolset by now, either a cross compiler or Native#Error ("gcc toolset: Toolchain not found for: $GCCTarget" )unless ( $tools_found );if ( defined $GCCToolchain ){## Parse GCCToolchain. Potential parts to create# GCCRoot - Location to find the effective /usr/include directory# GCCBin - Path to the gcc executable# GCCAr - Path to the ar executable# GCCFlags - Additional compiler flags. Also Production and Debug#$GCCRoot = $GCCToolchain->{ROOT};$GCCBin = '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'gcc';$GCCAr = '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'ar';$GCCGcovTool = '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'gcov';$GCCObjCopy = '${GCC_ROOT}/' . $GCCToolchain->{BASE} . 'objcopy';if (exists $GCCToolchain->{RPATH}) {if( $GCCToolchain->{RPATH} =~ m~^/~ ) {$GCCRPath = $GCCToolchain->{RPATH};} else {$GCCRPath = '${GCC_ROOT}/' . $GCCToolchain->{RPATH};}}$GCCFlags = $GCCToolchain->{CC_OPTS};$GCCFlagsP = $GCCToolchain->{CC_OPTSP};$GCCFlagsD = $GCCToolchain->{CC_OPTSD};$GCCXXFlags = $GCCToolchain->{CXX_OPTS};$LDFlags = $GCCToolchain->{LDFLAGS} if defined($GCCToolchain->{LDFLAGS});$PkgArch = $GCCToolchain->{PACKAGE_ARCH};SetGlobalOption('PACKAGE_ARCH', $PkgArch) if defined $PkgArch;}else{$GCCRoot = '/usr';$GCCBin = 'gcc';$GCCAr = 'ar';$GCCObjCopy = 'objcopy';}## When running under gcov we need to instruct GCC to perform code coverage# generation in both C flags and LD flags#if ( $UseGcov ){$GCCFlags .= ' -coverage';$LDFlags .= ' -coverage';}## When running with cppcheck we need to include it in our environment#if ( $UseCppcheck ){ToolsetRequire( "cppcheck" );PlatformDefine( "CPPCHECK_PLATFORM := unix32" );}#.. Define GCC environment#PlatformDefine( "################################################## GCC toolchain definitions##..");PlatformDefine( "GCC_TARGET := $GCCTarget" );PlatformDefine( "GCC_ROOT := $GCCRoot" );PlatformDefine( "GCC_CC := $GCCBin" );PlatformDefine( "GCC_AR := $GCCAr" );PlatformDefine( "GCC_OBJCOPY := $GCCObjCopy" );PlatformDefine( "GCC_GCOVTOOL := $GCCGcovTool" );PlatformDefine( "GCC_CFLAGS := $GCCFlags" ) if defined $GCCFlags;PlatformDefine( "GCC_CFLAGSP := $GCCFlagsP" ) if defined $GCCFlagsP;PlatformDefine( "GCC_CFLAGSD := $GCCFlagsD" ) if defined $GCCFlagsD;PlatformDefine( "GCC_LDFLAGS := $LDFlags" ) if defined $LDFlags;PlatformDefine( "GCC_CXXFLAGS := $GCCXXFlags" ) if defined $GCCXXFlags;## Required since this toolset advertises: ScmToolsetCompilerPath#PlatformDefine( "SCM_COMPILERPATH := \$\{GCC_CC\}" );## Sanity checking#PlatformDefine( "GCC_EVERSION := " . $GCCToolchain->{VERSION} ) if defined $GCCToolchain->{VERSION};PlatformDefine( "GCC_EMACHINE := " . $GCCToolchain->{MACHINE} ) if defined $GCCToolchain->{MACHINE};## Option indication of packaging architecture# Used by non-embedded systems for packaging. See debian_packager#PlatformDefine( "PACKAGE_ARCH := $PkgArch" ) if (defined $PkgArch);PlatformDefine( "" );#.. Piece the world together#Init( 'gcc' );ToolsetDefines( "gcc.def" );ToolsetRules( "gcc.rul" );ToolsetRules( "standard.rul" );PlatformDefine( "CTAGS_EXE:= ctags" );ToolsetRequire( "exctags" ); # and Exuberant Ctags# 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'noversiondll' => { 'NO_VERSIONED_DLLS', 1 }, # Matches usage elsewhere'pic' => { 'GEN_PIC' , '1' }, # Force PIC for static libs'nopic' => { 'GEN_PIC' , undef }, # No Pic on Static libs'brokenldscripts' => { 'BROKEN_LDSCRIPTS' , 1 }, # the linker is broken and cannot handle linker scripts);## Set default options#$::ScmCompilerOpts{'STATIC_PROGS'} = undef;$::ScmCompilerOpts{'NO_VERSIONED_DLLS'} = undef;$::ScmCompilerOpts{'USE_PROFILE'} = 1 if $UseProfile;## Process toolset-specfic compiler options#if ( exists $GCCToolchain->{COMPILER_OPTIONS} ){CompileOptions('*', split(',',$GCCToolchain->{COMPILER_OPTIONS}) );}}################################################################################ ToolsetCTAGS()# This subroutine takes the user options and builds the rules# required to build the CTAGS database.## Arguments:# --xxx No arguments currently defined## Output:# [ctags:]# $(EXCTAGS)################################################################################sub ToolsetCTAGS{EXCTAGS( @_ ) unless $ScmNoToolsTest;}################################################################################ 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" );if ( $UseGcov ){ToolsetGenerate( '$(OBJDIR)/' . $file . '.gcno' );ToolsetGenerate( '$(OBJDIR)/' . $file . '.gcda' );}}################################################################################ 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" );if ( $UseGcov ){ToolsetGenerate( '$(OBJDIR)/' . $file . '.gcno' );ToolsetGenerate( '$(OBJDIR)/' . $file . '.gcda' );}}################################################################################ 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 Shared Library '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( $linkname, $soname, $shared, $dbgname, @preReqFiles, @scripts, $multi_scan );my $sosuffix;my $noVersionedLib = $::ScmCompilerOpts{'NO_VERSIONED_DLLS'};my $brokenLd = $::ScmCompilerOpts{'BROKEN_LDSCRIPTS'};#.. 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#my $def = MakeSrcResolve($1);if ($brokenLd) {# The linker cannot handle the linker script# The work around is to split the script into two that it can handle# Only works with a Linker Script with VERSION and EXTERN entriesmy $index = scalar @ldFixups;my %data;$data{src} = $def;$data{vs} = '$(OBJDIR)/linkscript_' . $index . '.def';$data{ls} = '$(OBJDIR)/linkscript_' . $index . '.scr';push @ldFixups, \%data;push @scripts, $data{ls};push @scripts, '--version-script=' . $data{vs};push @preReqFiles, $data{vs};push @preReqFiles, $data{ls};} else {# Normal operation. Linker is not brokenpush @preReqFiles, $def;if ( $1 =~ m~\.def$~ ) {$def = '--version-script=' .$def; # Old def file}push @scripts, $def;}} elsif ( /^--MultiScan/i ) {$multi_scan = 1;} elsif ( /^--NoMultiScan/i ) {$multi_scan = 0;} elsif ( /^--SoNameSuffix=(.*)/i ) {$sosuffix = $1;} elsif (/^--NoVersionDll/i) {$noVersionedLib = 1;} else {Message( "SHLD: unknown option $_ -- ignored\n" );}}## Determine the 'soname' if none has been provided#$sosuffix = '.' . $verunless ( defined $sosuffix );$sosuffix = ''if ( $noVersionedLib );#.. Various library names#$linkname = "$name\$(GBE_TYPE).$::so";$shared = $noVersionedLib ? $linkname : "$linkname.$ver";$soname = "$linkname$sosuffix";my $shared_path = "\$(LIBDIR)/${shared}";my $dbg_path = $shared_path . '.dbg';#.. Cleanup rules## map Map file# ln Link from LIBDIR to BINDIR#ToolsetGenerate( "\$(LIBDIR)/${name}.map" );ToolsetGenerate( "\$(LIBDIR)/${shared}" );ToolsetGenerate( "\$(BINDIR)/${soname}" );ToolsetGenerate( $dbg_path );#.. 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" );PackageShlibAddFiles( $name, $dbg_path );$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->Entry( "", "", " \\\n\t\t", "", @preReqFiles );$io->Prt( "\n\t\$(SHLD)" );$io->Prt( "\n\t\$(call LDSTRIP,$shared_path,$dbg_path)\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)#if ( $shared ne $linkname){$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\n" );}$io->Label( "Shared library BINDIR Symbolic Links", $name );# PackageShlibAddFiles( $name, "\$(BINDIR)/$soname", 'symlink=1' );$io->Prt( "\$(BINDIR)/$soname:\t\\\n" ."\t\t\$(GBE_BINDIR)\\\n" ."\t\t\$(LIBDIR)/${shared}\n" ."\t\$(AA_PRE)(rm -f \$@; ln -s ../\$(LIBDIR)/$shared \$@)\n\n" );if ( $soname ne $shared ){$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 );ToolsetLibStd( $pLibs ); # push standard libraries$io->Cmd( "-Wl," . join (',', @scripts) ) if (@scripts);$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,# 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);}################################################################################ 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 $map = $base . '.map';my $ld = $base . '.ld';my $dbg = $base . '.dbg';#.. Cleanup rules#ToolsetGenerate( $ld );ToolsetGenerate( $map );ToolsetGenerate( $dbg );#.. Build rules#my ($io) = ToolsetPrinter::New();my $dep = $io->SetLdTarget( $name );$io->Prt( "$full : $dep " );$io->Entry( "", "", "\\\n\t", ".$::o ", @$pObjs );$io->Prt( "\n\t\$(LD)" );$io->Prt( "\n\t\$(call LDSTRIP,$full,$dbg)\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);# Add Compilers sysroot library path# Only required for a 'native' compiler that is not fully installed on the host# ie: The run-time can't locate the required glibc componentsif ($GCCRPath){$io->Cmd( "-Wl,-rpath=$GCCRPath" );$io->Cmd( "-Wl,--dynamic-linker=$GCCRPath/ld-linux.so.2" ) if ($GCCRPath);}$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();#.. Package up the program and other artifacts#PackageProgAddFiles ( $name, $full );PackageProgAddFiles ( $name, $dbg, "Class=debug" );}#-------------------------------------------------------------------------------# Function : ToolsetPostprocess## Description : Last chance by the toolset to perform processing# All Directives have been processed## If automated unit test are being used,# then we need to post process the results## Inputs : None## Returns :#sub ToolsetPostprocess{ToolsetPreprocessTests();ToolsetPostprocessTests();ToolsetCollateTestResults();ToolsetGenLdScripts();}################################################################################ Function : ToolsetPreprocessTests## Description : Generate $(OBJDIR)/lcov-baseline.info# Generate full coverage info## Inputs : None## Returns : Nothing## Output: : Rules and recipes to run before unit tests#sub ToolsetPreprocessTests{my ($io) = ToolsetPrinter::New();if ( $UseGcov && scalar(keys %::OBJSOURCE) > 0 ){## Setup Env so that the files created by GCOV are within the package# being created. Elsewise they will be created all over the file# system in the original location where the external objects were created.#$io->PrtLn('GCOV_PREFIX := $(abspath $(INTERFACEDIR)/gcov)' );$io->PrtLn('GCOV_PREFIX_STRIP := 0' );$io->PrtLn('export GCOV_PREFIX GCOV_PREFIX_STRIP' );$io->Newline();## GCOV_PKGBASE - used to 'extract' coverage artifacts# Used to limit the coverage report to files that are within this package# Ideally it should be the root of the package, but this is not always known# Use the first two path elements of the current package# Really just want to filter out compiler bits#$io->PrtLn('GCOV_PKGBASE := $(subst $(space),/,$(space)$(wordlist 1,2,$(subst /,$(space),$(CURDIR))))' );$io->PrtLn('GCOV_VERBOSE := $(if $(VERBOSE_OPT),,--quiet)' );$io->Newline();my $ruleName = 'preprocess_gcov_data';my $finaldir='$(LOCALDIR)/lcov/$(GBE_PLATFORM)$(GBE_TYPE)';my $final=$finaldir . '/lcov-final.info';ToolsetAddUnitTestPreProcess($ruleName);$io->PrtLn('.PHONY: ' . $ruleName );$io->PrtLn($ruleName . ': $(OBJDIR)' );$io->PrtLn("\t" . '${XX_PRE}$(rm) -f ${GCOV_PREFIX}/$(CURDIR)/$(OBJDIR)/*.gcda' );$io->PrtLn("\t" . '${XX_PRE}$(rm) -f $(OBJDIR)/*.gcda' );$io->PrtLn("\t" . '${XX_PRE}$(rm) -f ' . $final);$io->PrtLn("\t" . '${XX_PRE}lcov'. ' $(GCOV_VERBOSE)'. ' --capture'. ' --initial'. ' --base-directory $(CURDIR)'. ' --directory $(OBJDIR)'. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file $(OBJDIR)/lcov-baseline.info' );$io->Newline();ToolsetGenerate( '$(OBJDIR)/lcov-baseline.info' );}}################################################################################ Function : ToolsetPostprocessTests## Description : Merge this sub-components bits into the the final coverage# file in lcov-baseline.info## Need to locate the .gcda files and place them in the same directory# as the .gcno files that were created during preprocssing## Then we can add our trace bits into the file coverage file## Inputs : None## Returns : Nothing## Output: : Rules and recipes to run after the unit tests#sub ToolsetPostprocessTests{my ($io) = ToolsetPrinter::New();if ( $UseGcov && scalar(keys %::OBJSOURCE) > 0 ){my $ruleName = 'postprocess_gcov_data';my $finaldir='$(LOCALDIR)/lcov/$(GBE_PLATFORM)$(GBE_TYPE)';my $final=$finaldir . '/lcov-final.info';ToolsetAddUnitTestPostProcess($ruleName);$io->PrtLn('.PHONY: ' . $ruleName );$io->PrtLn($ruleName . ':' );$io->PrtPart("\t" . '$(XX_PRE)if [ -d "${GCOV_PREFIX}/$(CURDIR)/$(OBJDIR)" ]; then' );$io->PrtPart("\t\t" . 'cd ${GCOV_PREFIX}/$(CURDIR);');$io->PrtPart("\t\t" . 'find $(OBJDIR) -name \'*.gcda\' -exec cp --parent {} $(CURDIR) \\; ;');# $io->PrtPart("\t" . 'else');# $io->PrtPart("\t\t" . 'echo NO .gcda DATA for $(CURDIR);');$io->PrtLn ("\t" . 'fi' );$io->PrtLn ("\t" . '$(XX_PRE)$(mkdir) -p ' . $finaldir);$io->PrtPart("\t" . '$(XX_PRE)GCDA_COUNT=$$(find $(OBJDIR) -name "*.gcda" | wc -l);' );$io->PrtPart("\t" . 'if [ "$${GCDA_COUNT}" -eq "0" ]; then ');$io->PrtPart("\t\t" . 'if [ ! -e ' . $final . " ]; then");$io->PrtPart("\t\t\t" . '$(cp) $(OBJDIR)/lcov-baseline.info ' . $final . ';');$io->PrtPart("\t\t" . 'else');$io->PrtPart("\t\t\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --add-tracefile $(OBJDIR)/lcov-baseline.info'. ' --add-tracefile ' . $final. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file $(OBJDIR)/lcov-merge.info'. ';');$io->PrtPart("\t\t\t" . '$(rm) -f ' . $final . ';');$io->PrtPart("\t\t\t" . '$(mv) $(OBJDIR)/lcov-merge.info ' . $final . ';');$io->PrtPart("\t\t" . 'fi' . ';');$io->PrtPart("\t" . 'else');$io->PrtPart("\t\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --capture'. ' --base-directory $(CURDIR)'. ' --directory $(OBJDIR)'. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file $(OBJDIR)/lcov-capture.info'. ';');$io->PrtPart("\t\t" . 'if [ ! -e ' . $final . " ]; then");$io->PrtPart("\t\t\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --add-tracefile $(OBJDIR)/lcov-baseline.info'. ' --add-tracefile $(OBJDIR)/lcov-capture.info'. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file ' . $final. ';');$io->PrtPart("\t\t" . 'else');$io->PrtPart("\t\t\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --add-tracefile $(OBJDIR)/lcov-baseline.info'. ' --add-tracefile $(OBJDIR)/lcov-capture.info'. ' --add-tracefile ' . $final. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file $(OBJDIR)/lcov-merge.info'. ';');$io->PrtPart("\t\t\t" . '$(rm) -f ' . $final . ';');$io->PrtPart("\t\t\t" . '$(mv) $(OBJDIR)/lcov-merge.info ' . $final . ';');$io->PrtPart("\t\t" . 'fi' . ';');$io->PrtLn ("\t" . 'fi');$io->Newline();ToolsetGenerate ('$(OBJDIR)/lcov-capture.info' );ToolsetGenerate ($final);}}################################################################################ Function : ToolsetCollateTestResults## Description : Process the lcov-final.info by# Extract parts generated by files in this package# Remove parts generated by files in the interface directory# They are the results of a 'BuildPkgArchive'## Inputs : None## Returns : Nothing## Output: : Rules and recipes to run after unit test result# postprocessing.#sub ToolsetCollateTestResults{my ($io) = ToolsetPrinter::New();if ( $UseGcov && scalar(keys %::OBJSOURCE) > 0 ){my $ruleName = 'collate_gcov_results';my $finaldir = '$(LOCALDIR)/lcov/$(GBE_PLATFORM)$(GBE_TYPE)';my $final = $finaldir . '/lcov-final.info';my $finalTmp = $finaldir . '/lcov-extracted.info';my $finalTmp1 = $finaldir . '/lcov-filtered.info';ToolsetGenerate ( $final );ToolsetGenerate ( $finalTmp );ToolsetGenerate ( $finalTmp1 );ToolsetAddUnitTestCollateProcess($ruleName);my $reportdir='$(PKGDIR)/lcov/$(GBE_PLATFORM)$(GBE_TYPE)';my $reportindex=$reportdir . '/index.html';$io->PrtLn('.PHONY: ' . $ruleName );$io->PrtLn($ruleName . ': ' . $reportindex);$io->Newline();$io->PrtLn($reportindex . ': ' . $final);$io->PrtPart("\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --extract '. $final .' "$(GCOV_PKGBASE)/*"'. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file ' . $finalTmp. ';');$io->PrtPart("\t" . 'lcov'. ' $(GCOV_VERBOSE)'. $LcovExplicitBranch. ' --remove '. $finalTmp .' "$(abspath $(INTERFACEDIR))/*"'. ' --gcov-tool $(GCC_GCOVTOOL)'. ' --output-file ' .$finalTmp1. ';');$io->PrtLn("\t" . 'genhtml'. ' $(GCOV_VERBOSE)'. ' --frames'. ' --show-details'. ' --function-coverage'. ' --branch-coverage'. ' --output-directory ' . $reportdir. ' --legend'. ' --demangle-cpp'. ' --title "$(GBE_PBASE) $(BUILDVER)"'. ' ' . $finalTmp1);$io->Newline();}}#-------------------------------------------------------------------------------# Function : ToolsetGenLdScripts## Description : Generate Linker (ld) scripts to to support the Broken Linker# Enabled via BROKEN_LDSCRIPTS# The linker cannot handle a linkerscript with a 'VERSION" section# The linker can handle a linker script with an EXTERN section# and a --version-script## This workaround will take the linker script and break it into two# parts. This must be done at make-time in case the linker script is# generated.## Use a feature of Pattern Rules. Handling of multiple targets# The pattern (%) is a '.'.# It may be substituted as $* in the output.## file1%out file2%out : infile# SomeProg file1$*out file2$*out - Using pattern substitution# SomeProg file1.out file2.out - Alternate command## Inputs : None## Returns : Nothing#sub ToolsetGenLdScripts{return unless @ldFixups;Verbose('ToolsetGenLdScripts');my ($io) = ToolsetPrinter::New();$io->PrtLn('# Broken Linker Support');foreach my $entry (@ldFixups){(my $ls = $entry->{ls}) =~ s~\.~%~;(my $vs = $entry->{vs}) =~ s~\.~%~;$io->Newline();$io->PrtLn("$vs $ls: $entry->{src} \$(SCM_MAKEFILE)" );$io->PrtLn("\t\$(GBE_PERL) -Mjats_runtime_gcc -e splitscript -- --src=$entry->{src} --vs=$entry->{vs} --ls=$entry->{ls}" );ToolsetGenerate ($entry->{vs} );ToolsetGenerate ($entry->{ls} );}}################################################################################ ToolsetARLINT( $name, \@args, \@objs )# This subroutine takes the user options and builds the rules# required to lint the static library 'name'.## Arguments:# --xxx No arguments currently defined## Output:# [ $(LIBDIR)/name$_lint: .... ]# $(ARLINT)################################################################################sub ToolsetARLINT{if ( $UseCppcheck ){CppcheckAR( @_ );}}################################################################################ ToolsetSHLDLINT $name, \@args, \@objs, \@libraries )# This subroutine takes the user options and builds the rules# required to lint the shared library 'name'.## Arguments:# (none)## Output:# [ $(LIBDIR)/$name_lint: .... ]# $(SHLIBLINT)################################################################################sub ToolsetSHLDLINT{if ( $UseCppcheck ){CppcheckSHLD( @_ );}}################################################################################ ToolsetLD( $name, \@args, \@objs, \@libraries, \@csrc, \@cxxsrc )# This subroutine takes the user options and builds the rules# required to lint the program 'name'.## Arguments:# (none)## Output:# [ $(BINDIR)/$name_lint: .... ]# $(LDLINT)################################################################################sub ToolsetLDLINT{if ( $UseCppcheck ){CppcheckLD( @_ );}}########################################################################## 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;