# 
#  * px *
# Copyright (c) 2008 Shawn Hladky
# 
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software 
# and associated documentation files (the "Software"), to deal in the Software without 
# restriction, including without limitation the rights to use, copy, modify, merge, publish, 
# distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
# Software is furnished to do so, subject to the following conditions:
# 
# The above copyright notice and this permission notice shall be included in all copies or 
# substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
#


#
# For Linux 2.6: export OSVER=26  (or the appropriate number for your system)
# 

# These Jamrules mostly copied from the P4API distribution.

rule SetLibName
{
    $(1) = $(2:S=$(SUFLIB)) ;
    LOCATE on $($(1)) = $(EXEC) ;
}


#####################################################################
# P4API libs and includes.
#####################################################################

rule IncludeP4API
{
    # Add includes for building P4API apps.
    if ! $(P4APIDIR)
    {
        Exit Please set P4APIDIR to the path of the P4API distribution. ;
    }

    P4INCLUDE = $(P4APIDIR)$(SLASH)include$(SLASH)p4 ;
    P4LIBS    = $(P4APIDIR)$(SLASH)lib ;

    SubDirHdrs $(P4INCLUDE) ;

    SetLibName CLIENTLIB  : libclient ;
    SetLibName RPCLIB     : librpc    ;
    SetLibName SUPPORTLIB : libsupp   ;

    CLIENTLIB  = $(P4LIBS)$(SLASH)$(CLIENTLIB)  ;
    RPCLIB     = $(P4LIBS)$(SLASH)$(RPCLIB)     ;
    SUPPORTLIB = $(P4LIBS)$(SLASH)$(SUPPORTLIB) ;
}


###################################################################
# OS settings.
###################################################################

    if $(OS) = NT 
    {
        JAMSHELL = cmd.exe /c ;
    }

    GENFLAGS = CCFLAGS C++FLAGS ;

    switch $(OS)$(OSVER) $(OS)
    {
    case CYGWIN :
        STRIP = ;
        CC = gcc ;
        C++ = gcc ;
        LINK = g++ ;
        C++FLAGS += -DUSE_CRLF ;

    case FREEBSD :
        Exit Set OSVER to 4, 5, or 6 for FreeBSD ;

    case FREEBSD4 :
        CC   = gcc ;
        C++  = g++ ;
        LINK = gcc ;

        switch $(OSCOMP)
        {
        case GCC3 : LINKLIBS += -lsupc++ ;
        }

        if $(OSPLAT) != AXP { LINKFLAGS += -static ; }
        $(GENFLAGS) += -pipe ;

    case FREEBSD[56789]* :
        CC   = gcc ;
        C++  = g++ ;
        LINK = gcc ;
        # supc++ library on freebsd5.x and later is missing some
        # modules (this is a bug), so we can't use it.
        # But we still do not want to link stdc++ dynamically.
        #LINKLIBS += -lsupc++ ;
        LINKLIBS += -Wl,-dn,-lstdc++,-dy ;

        _mflags = ;
        switch $(OSPLAT)
        {
        case X86    : _mflags = -m32 ;
        case X86_64 : _mflags = -m64 ;
        }

        $(GENFLAGS) += $(_mflags) -pipe ;
        LINKFLAGS   += $(_mflags) ;

        QTOPENGL ?= no ;

    case LINUX :
        Exit Set OSVER to 24 or 26 ;

    case LINUX24 :
        CC   = gcc ;
        C++  = g++ ;
        LINK = gcc ;
        LINKLIBS += -lsupc++ ;  # Assumes gcc 3.x or later

        # be explicit about submodel since we may be compiling x86 code on
        # an x86/x86_64 biarch system, and the default may be uncertain.
        _mflags = ;
        switch $(OSPLAT)
        {
        case X86    : _mflags = -m32 ;
        case X86_64 : _mflags = -m64 ;
        }
        LINKLIBS on p4d += $(LINKLIBS) -ldl ;
        LINKLIBS on p4p += $(LINKLIBS) -ldl ;
        LINKLIBS on p4web += $(LINKLIBS) -ldl ;

        if $(SMARTHEAP) = yes { $(GENFLAGS) += -DUSE_SMARTHEAP ; }

        $(GENFLAGS) += $(_mflags) -D_GNU_SOURCE ;
        LINKFLAGS   += $(_mflags) ;

        QTOPENGL ?= no ;

    case LINUX26 :
        CC   = gcc ;
        C++  = g++ ;
        LINK = g++ ;    #gcc didn't work for me... switch to g++
        LINKLIBS += -lsupc++ ;

        LINKLIBS on p4d += $(LINKLIBS) -ldl ;
        LINKLIBS on p4p += $(LINKLIBS) -ldl ;
        LINKLIBS on p4web += $(LINKLIBS) -ldl ;

        # be explicit about submodel since we may be compiling x86 code on
        # an x86/x86_64 biarch system, and the default may be uncertain.
        _mflags = ;
        switch $(OSPLAT)
        {
        case X86    : _mflags = -m32 ;
        case X86_64 : _mflags = -m64 ;
        case AXP    : LINKFLAGS += -static ;
        }

        if $(SMARTHEAP) = yes { $(GENFLAGS) += -DUSE_SMARTHEAP ; }

        $(GENFLAGS) += $(_mflags) -D_GNU_SOURCE ;
        LINKFLAGS   += $(_mflags) ;

        QTOPENGL ?= no ;

    case MACOSX :
        CC = cc ;
        C++ = cc ;
        $(GENFLAGS) += -DCASE_INSENSITIVE ;
        $(GENFLAGS) += -fpascal-strings ;
        # This looks like a flag but it is really a library macro
        # kind of thing and causes link problems if it at the front
        # of the link command so we make it a LIB
        LINKLIBS += -framework Carbon ;

    case MACOSX104 :  # assumes using gcc 4.0.1 or newer
        CC   = gcc ;
        C++  = g++ ;
        LINK = g++ ;

        MACOSX_SDK ?= /Developer/SDKs/MacOSX10.4u.sdk ;

        # The -fvisibility-inlines-hidden option is a C++-only
        # option, needed because Qt4 is built with it and all
        # statically-compiled objects need to use it consistently.
        C++FLAGS    += -fvisibility-inlines-hidden ;
        $(GENFLAGS) += -DCASE_INSENSITIVE
                       -fpascal-strings
                       -isysroot$(MACOSX_SDK) ;
        LINKFLAGS   += -Wl,-syslibroot,$(MACOSX_SDK) ;
        # This looks like a flag but it is really a library macro
        # and causes link problems if it's at the front of the link
        # command, so we make it a LIB.
        LINKLIBS    += -framework Carbon ;

        switch $(OSPLAT)
        {
        # Note: we may elect at some point to generate universal
        # binaries, in which case just add multiple -arch [arch]
        # flags here.
        #case X86   : _arch = -arch i386 -arch ppc ;
        case X86    : _arch = -arch i386   ;
        case X86_64 : _arch = -arch x86_64 ;
        case *      : _arch = -arch ppc    ;
        }

        $(GENFLAGS) += $(_arch) -DCASE_INSENSITIVE ;
        LINKFLAGS   += $(_arch) ;

        # This adds $(QTDIR)/lib as a frameworks directory, in case
        # Qt is built as frameworks.  On the mac, it can be built
        # either as frameworks, regular unix-style shared
        # libraries, or unix-style static libaries.
        $(GENFLAGS)  += -F$(QTDIR)/lib ;

    case NT* :
        # Use setargv.obj to get wildcard expansion.
        # The "rc" tool needs MS headers:

        BINDIR = e:\\perforce ;
        JAMSHELL ?= $(P4)\\Jamsh.bat $(OSPLAT) % "!" ;

        C++FLAGS += /DCASE_INSENSITIVE /DUSE_CRLF /wd4996 /wd4530 /DOS_NT ;
        if $(SMARTHEAP) = yes { $(GENFLAGS) += /DUSE_SMARTHEAP ; }

        LINKLIBS = setargv.obj advapi32.lib oldnames.lib
                kernel32.lib ws2_32.lib ;
        STDHDRS = $(MSVCNT)\\include $(MSVCNT)\\atlmfc\\include ;
        STRIP = ;

        # Now, unset STDHDRS so Jam doesn't scan system headers (takes
        # too long when using compiler on networked machine):

        STDHDRS = ;

        if $(BCCROOT)
        {
        # Jeff Anton compiles with borland.

        OPTIM = -O2 ;
        RCFLAGS = /d NDEBUG /r ;
        AR = tlib /C /P128 ;
        LINKLIBS = $(BCCROOT)/lib/wildargs.obj ;
        }
        else if $(TYPE) = g
        {
        # Debugging build

        OPTIM = /Zi /Gm ;
        RCFLAGS = /d DEBUG /r ;
        LINKFLAGS += /DEBUG ;
        $(GENFLAGS) += /MTd ;
        }
        else if $(TYPE) = dyn
        {
        # Dynamic link version, for qt products

        if $(JAMFAST)
        {
            OPTIM = /Z7 /O2 ;
        }
        else
        {
            OPTIM = /Zi /O2 ;
            actions Cc
            {
            $(CC) /c /Fo$(<) /Fd$(EXEC)\ $(CCFLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" $(>)
            }
            actions C++
            {
            $(C++) /c /Fo$(<) /Fd$(EXEC)\ $(C++FLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" /Tp$(>)
            }
        }
        RCFLAGS = /d NDEBUG /r ;
        $(GENFLAGS) += /MD ;
        LINKFLAGS += /MAP /OPT:REF /OPT:ICF /DEBUG ;
        }
        else if $(TYPE) = dyng
        {
        # Dynamic Debugging build
        if $(JAMFAST)
        {
            OPTIM = /Z7 ;
        }
        else
        {
            OPTIM = /Zi /Gm ;
            actions Cc
            {
            $(CC) /c /Fo$(<) /Fd$(EXEC)\ $(CCFLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" $(>)
            }
            actions C++
            {
            $(C++) /c /Fo$(<) /Fd$(EXEC)\ $(C++FLAGS) $(CCDEFS) $(CCHDRS) /I"$(STDHDRS)" /Tp$(>)
            }
        }
        RCFLAGS = /d DEBUG /r ;
        $(GENFLAGS) += /MDd ;
        LINKFLAGS += /DEBUG /NODEFAULTLIB:msvcrt.lib  /fixed:no ;
        }
        else if $(TYPE) = vsdebug
        {
        # Static link with Visual Studio debug libraries.
        # This does not enable debugging our own code, just sets
        # linker dependencies for VS libraries.
        # This is intended for customer use.

        OPTIM        = /O2 ;
        RCFLAGS      = /d NDEBUG /r ;
        $(GENFLAGS) += /MTd ;
        LINKFLAGS   += /MAP ;
        }
        else if $(TYPE) = dyn_vsdebug
        {
        # Dynamic link with Visual Studio debug libraries.
        # This does not enable debugging our own code, just sets
        # linker dependencies for VS libraries.
        # This is intended for customer use.

        OPTIM        = /O2 ;
        RCFLAGS      = /d NDEBUG /r ;
        $(GENFLAGS) += /MDd ;
        LINKFLAGS   += /MAP /OPT:REF /OPT:ICF ;
        }
        else if $(OSVER) = 98
        {
        # Dynamic link version for win98 version of p4win
        # Goes into bin.win98 -- oddity.

        EXEC = [ FSubDirPath P4BIN bin.win98 ] ;
        ALL_LOCATE_TARGET = $(EXEC) ;

        OPTIM = /O2 ;
        if $(TYPE_DEBUG) = true { OPTIM += /Zi ; }

        RCFLAGS = /d NDEBUG /r ;
        $(GENFLAGS) += /MD ;
        LINKFLAGS = /MAP ;
        }
        else
        {
        # Static link version, for command line products

        OPTIM = /O2 ;
        RCFLAGS = /d NDEBUG /r ;
        $(GENFLAGS) += /MT ;
        LINKFLAGS += /MAP ;
        }

    case * :
        Exit Don't know "$(OS)$(OSVER) or " $(OS) ;
    }


#####################################################################
# Set up output directory.
# Jamfile should use "SubDir BIN ;" to specify the current directory
# as the root where the bin.* subdirectories will live.
#####################################################################

    EXEC_LIB_TOKENS =
        BIN
        lib.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
        ;
    EXEC_LIB ?= [ FSubDirPath $(EXEC_LIB_TOKENS) ] ;

    EXEC_LIBEXEC_TOKENS =
        BIN
        libexec.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
        ;
    EXEC_LIBEXEC ?= [ FSubDirPath $(EXEC_LIBEXEC_TOKENS) ] ;

    # Build dir: p4-bin/bin.xxx[/build][/type]
    EXEC_TOKENS =
        TOP
        bin
        bin.$(OS:L)$(OSVER:EL)$(OSPLAT:EL)
        $(BUILD)
        $(TYPE:L)
        ;

    EXEC ?= [ FSubDirPath $(EXEC_TOKENS) ] ;
    ALL_LOCATE_TARGET = $(EXEC) ;