# (C) Copyright David Abrahams 2001. Permission to copy, use,
# modify, sell and distribute this software is granted provided this
# copyright notice appears in all copies. This software is provided
# "as is" without express or implied warranty, and with no claim as
# to its suitability for any purpose.

# The following #// line will be used by the regression test table generation
# program as the column heading for HTML tables. Must not include version number.
#//<a href="http://gcc.gnu.org/">GNU<br>GCC</a>

# compute directories for invoking GCC
#
# The gcc toolset can be user-configured using the following
# variables:
#
# GCC_ROOT_DIRECTORY
#       The directory in which GCC was installed. Defaults to
#       unset. Usually, there is no need to set this variable at
#       all. However, if G++ is not in the path it is usually
#       sufficient to configure this one variable. More fine-grained
#       configuration is available by setting the following:
#
# GCC_BIN_DIRECTORY
#       the directory prefix used to find the gcc executables. Defaults to
#       $(GCC_ROOT_DIRECTORY)/bin/, or "" if GCC_ROOT_DIRECTORY is
#       not set.
#
# GCC_INCLUDE_DIRECTORY
#       the directory in which to find system includes. Defaults to
#       $(GCC_ROOT_DIRECTORY)/include. 
#
# GCC_STDLIB_DIRECTORY
#       the directory in which to find the standard library
#       objects associated with this build of gcc. Defaults to
#       $(GCC_ROOT_DIRECTORY)/lib. 
#
# GXX
#       The name by which g++ is invoked. You can also use this in
#       lieu of setting the <cxxflags> property to force options such
#       as "-V3.0.4" into the g++ command line: "-sGXX=g++ -V3.0.4".
#
# GCC
#       Similar to GXX, the name by which gcc is invoked for "C"
#       language targets.

# singleton variables...
set-as-singleton GCC_ROOT_DIRECTORY GCC_BIN_DIRECTORY GCC_INCLUDE_DIRECTORY GCC_STDLIB_DIRECTORY ;

GCC_BIN_DIRECTORY ?= $(GCC_ROOT_DIRECTORY)/bin/ ;
GCC_BIN_DIRECTORY ?= "" ; # Don't clobber tool names if GCC_ROOT_DIRECTORY not set
GCC_INCLUDE_DIRECTORY ?= $(GCC_ROOT_DIRECTORY)/include ;
GCC_STDLIB_DIRECTORY ?= $(GCC_ROOT_DIRECTORY)/lib ;

flags gcc LINKFLAGS <runtime-link>static : -static ;
flags gcc CFLAGS <debug-symbols>on : -g ;
flags gcc LINKFLAGS <debug-symbols>on : -g ;
flags gcc CFLAGS <optimization>off : -O0 ;
flags gcc CFLAGS <optimization>speed : -O3 ;

# Other optimizations we might want for GCC
# -fforce-mem -fomit-frame-pointer
# -foptimize-sibling-calls -finline-functions -ffast-math -finline-limit=10000

flags gcc CFLAGS <optimization>space : -Os ;
flags gcc CFLAGS <inlining>off : -fno-inline ;
flags gcc CFLAGS <inlining>on : -Wno-inline ;
flags gcc CFLAGS <inlining>full : -finline-functions -Wno-inline ;

#
# set threading options for various platforms:
#
if $(NT)
{
    flags gcc CFLAGS <threading>multi : -mthreads ;
}
else if $(UNIX)
{
    switch $(JAMUNAME)
    {
    case CYGWIN* :
        {
        flags gcc CFLAGS <threading>multi : -mthreads ;
        }
    case SunOS* :
        {
        flags gcc CFLAGS <threading>multi : -pthreads ;
        flags gcc LINKFLAGS <threading>multi : -pthreads ;
        flags gcc FINDLIBS <threading>multi : rt ;
        NO_GNU_LN = true ; # sun seems not to use the GNU linker with gcc
        }
    case BeOS :
        {
        # BeOS has no threading options, don't set anything here.
        }
    case Darwin :
        {
        # MacOS X, doesn't need any threading options set
        # -lpthread is linked to by default.
        # There is no gcc/g++, we need to use cc/c++ instead:
        GCC ?= cc ;
        GXX ?= c++ ;
        }
    case * :
        {
        flags gcc CFLAGS <threading>multi : -pthread ;
        flags gcc LINKFLAGS <threading>multi : -pthread ;
        flags gcc FINDLIBS <threading>multi : rt ;
        }
    }
}

# Set architecture options.
#
# x86 and compatible
flags gcc CFLAGS <architecture>i386 : -mcpu=i386 ;
flags gcc CFLAGS <architecture>i486 : -mcpu=i486 ;
flags gcc CFLAGS <architecture>i586 : -mcpu=i586 ;
flags gcc CFLAGS <architecture>i686 : -mcpu=i686 ;
flags gcc CFLAGS <architecture>k6 : -mcpu=k6 ;
# Sparc
flags gcc CFLAGS <architecture>v7 : -mcpu=v7 ;
flags gcc CFLAGS <architecture>cypress : -mcpu=cypress ;
flags gcc CFLAGS <architecture>v8 : -mcpu=v8 ;
flags gcc CFLAGS <architecture>supersparc : -mcpu=supersparc ;
flags gcc CFLAGS <architecture>sparclite : -mcpu=sparclite ;
flags gcc CFLAGS <architecture>hypersparc : -mcpu=hypersparc ;
flags gcc CFLAGS <architecture>sparclite86x : -mcpu=sparclite86x ;
flags gcc CFLAGS <architecture>f930 : -mcpu=f930 ;
flags gcc CFLAGS <architecture>f934 : -mcpu=f934 ;
flags gcc CFLAGS <architecture>sparclet : -mcpu=sparclet ;
flags gcc CFLAGS <architecture>tsc701 : -mcpu=tsc701 ;
flags gcc CFLAGS <architecture>v9 : -mcpu=v9 ;
flags gcc CFLAGS <architecture>ultrasparc : -mcpu=ultrasparc ;
# RS/6000 & PowerPC
flags gcc CFLAGS <architecture>rios : -mcpu=rios ;
flags gcc CFLAGS <architecture>rios1 : -mcpu=rios1 ;
flags gcc CFLAGS <architecture>rsc : -mcpu=rsc ;
flags gcc CFLAGS <architecture>rios2 : -mcpu=rios2 ;
flags gcc CFLAGS <architecture>rs64a : -mcpu=rs64a ;
flags gcc CFLAGS <architecture>601 : -mcpu=601 ;
flags gcc CFLAGS <architecture>602 : -mcpu=602 ;
flags gcc CFLAGS <architecture>603 : -mcpu=603 ;
flags gcc CFLAGS <architecture>603e : -mcpu=603e ;
flags gcc CFLAGS <architecture>604 : -mcpu=604 ;
flags gcc CFLAGS <architecture>604e : -mcpu=604e ;
flags gcc CFLAGS <architecture>620 : -mcpu=620 ;
flags gcc CFLAGS <architecture>630 : -mcpu=630 ;
flags gcc CFLAGS <architecture>740 : -mcpu=740 ;
flags gcc CFLAGS <architecture>750 : -mcpu=750 ;
flags gcc CFLAGS <architecture>power : -mcpu=power ;
flags gcc CFLAGS <architecture>power2 : -mcpu=power2 ;
flags gcc CFLAGS <architecture>powerpc : -mcpu=powerpc ;
flags gcc CFLAGS <architecture>403 : -mcpu=403 ;
flags gcc CFLAGS <architecture>505 : -mcpu=505 ;
flags gcc CFLAGS <architecture>801 : -mcpu=801 ;
flags gcc CFLAGS <architecture>821 : -mcpu=821 ;
flags gcc CFLAGS <architecture>823 : -mcpu=823 ;
flags gcc CFLAGS <architecture>860 : -mcpu=860 ;
flags gcc CFLAGS <architecture>power-common : -mcpu=common ;

#
# define compiler names if not set:
GCC ?= gcc ;
GXX ?= g++ ;


flags gcc CFLAGS <profiling>on : -pg ;
flags gcc LINKFLAGS <profiling>on : -pg ;

flags gcc C++FLAGS <rtti>off : -fno-rtti ;
flags gcc C++FLAGS <vtable-thunks>on : -fvtable-thunks ;
flags gcc C++FLAGS <vtable-thunks>off : -fvtable-thunks=0 ;

flags gcc CFLAGS <cflags> ;
flags gcc C++FLAGS <cxxflags> ;
flags gcc DEFINES <define> ;
flags gcc UNDEFS <undef> ;
flags gcc HDRS <include> ;
flags gcc STDHDRS <sysinclude> ;
flags gcc LINKFLAGS <linkflags> ;
flags gcc LINKFLAGS <debug-symbols>off : -s ;
flags gcc ARFLAGS <arflags> ;

flags gcc STDHDRS : $(GCC_INCLUDE_DIRECTORY) ;
flags gcc STDLIBPATH : $(GCC_STDLIB_DIRECTORY) ;

if ! $(ARFLAGS)
{
    flags gcc ARFLAGS : "" ;
}

if ! $(NT) # The compiler complains about -fPIC on NT
{
    flags gcc CFLAGS <shared-linkable>true : -fPIC ;
    flags gcc LINKFLAGS <shared-linkable>true : -fPIC ;
}


if $(BETOOLS)
{
    flags gcc LINKFLAGS <target-type>$(SHARED_TYPES) : -nostart ;
}
else
{
    flags gcc LINKFLAGS <target-type>$(SHARED_TYPES) : -shared ;
}

flags gcc LIBPATH <library-path> ;
flags gcc NEEDLIBS <library-file> ;
flags gcc FINDLIBS <find-library> ;

flags gcc DLLVERSION <dllversion> ;
DLLVERSION = $(DLLVERSION[1]) ;
DLLVERSION ?= $(BOOST_VERSION) ;

flags gcc TARGET_TYPE <target-type> ;

#### Link ####

rule Link-action
{
    SPACE on $(<) = " " ;
    # if we don't have a GNU linker then we can't pass any GNU-ld specific flags:
    if $(NO_GNU_LN)
    {
        LNOPT on $(<) = ;
    }
    else
    {
        LNOPT on $(<) = "" ;
    }
    # do we use sonames or not?
    if $(DLLVERSION) && $(TARGET_TYPE) in $(SHARED_TYPES) && $(OS) = LINUX && ! $(NO_GNU_LN)
    {
        OUTTAG on $(<) = ".$(DLLVERSION)" ;
        SOTAG on $(<) = ".$(DLLVERSION)" ;
        ACTION_1 on $(<) = "" ;
    }
    else
    {
        OUTTAG on $(<) = "" ;
        SOTAG on $(<) = ;
        ACTION_1 on $(<) = ;
    }
    # This will appear before the import library name when building a DLL, but
    # will be "multiplied away" otherwise. The --exclude-symbols directive
    # proved to be neccessary with some versions of Cygwin.
    IMPLIB_COMMAND on $(<) = "-Wl,--export-all-symbols -Wl,--exclude-symbols,_bss_end__:_bss_start__:_data_end__:_data_start__ -Wl,--out-implib," ;
    DEPENDS $(<) : $(NEEDLIBS) ;
    gRUN_LD_LIBRARY_PATH($(<)) += $(GCC_STDLIB_DIRECTORY) ;
    if $(<[2]) && $(NT) && ( -mno-cygwin in $(gBUILD_PROPERTIES:G=) )
    {
        gcc-dllwrap $(<) : $(>) ;
    }
    else
    {
        gcc-Link-action $(<) : $(>) ;
    }
}

# for gcc, we repeat all libraries so that dependencies are always resolved
actions gcc-Link-action bind NEEDLIBS
{
    $(SHELL_SET)LD_LIBRARY_PATH=$(RUN_LD_LIBRARY_PATH)
    $(SHELL_EXPORT)LD_LIBRARY_PATH
    $(GCC_BIN_DIRECTORY)$(GXX) $(IMPLIB_COMMAND)$(<[2]) $(LINKFLAGS) -o "$(<[1])$(OUTTAG)" -L$(LIBPATH:T) -L$(STDLIBPATH:T) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) $(LNOPT)-Wl,-rpath-link,.$(SPACE)"-Wl,-soname,$(<[1]:D=)$(SOTAG)"
    $(ACTION_1)$(LN)$(SPACE)-fs$(SPACE)"$(<[1]:D=)$(OUTTAG)"$(SPACE)"$(<[1])"
}

actions gcc-dllwrap bind NEEDLIBS
{
    dllwrap --dllname $(<[1]) -o foo.pyd $(>) -s --entry _DllMain@12 --target=i386-mingw32 -L$(LIBPATH:T) -L$(STDLIBPATH:T) "$(>)" "$(NEEDLIBS)" "$(NEEDLIBS)" -l$(FINDLIBS) -Wl,-rpath-link,. $(LINKFLAGS)     
}

#### Cc #####

rule Cc-action
{
    SPACE on $(<) = " " ;
    gcc-Cc-action $(<) : $(>) ;
}

actions gcc-Cc-action
{
    $(GCC_BIN_DIRECTORY)$(GCC) -c -Wall -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -isystem$(SPACE)"$(STDHDRS)" -o "$(<)" "$(>)"
}

#### C++ ####
rule C++-action
{
    SPACE on $(<) = " " ;
    gcc-C++-action $(<) : $(>) ;
}

actions gcc-C++-action
{
    $(GCC_BIN_DIRECTORY)$(GXX) -c -Wall -ftemplate-depth-100 -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -isystem$(SPACE)"$(STDHDRS)" -o "$(<)" "$(>)"
}

#### Archive ####

rule Archive-action
{
    gcc-Archive-action $(<) : $(>) ;
}

actions updated together piecemeal gcc-Archive-action
{
    ar ru$(ARFLAGS) "$(<:T)" "$(>:T)"
}
