# Tools Makefile fragment
#
# Expected inputs:
#
# COMPONENT_TYPE	Type of component:
# 				binary		-	Executable binary
# 				lib-static	-	Static library
# 				lib-shared	-	Shared library
# 				riscos-module	-	RISC OS module
#
# Optional inputs:
#
# BUILD			Type of build to perform:
# 				release		-	Release build (default)
# 				debug		-	Debug build
# OPTCFLAGS		Optional C compiler flags for $(BUILD)
# OPTCXXFLAGS		Optional C++ compiler flags for $(BUILD)
# OPTLDFLAGS		Optional linker flags for $(BUILD)
# TARGET		Target platform (defaults to host)
#

###############################################################################
# Sanity checks
###############################################################################

ifeq ($(COMPONENT_TYPE),)
  $(error COMPONENT_TYPE not set)
endif

# Default build to release
ifeq ($(BUILD),)
  BUILD := release
endif

###############################################################################
# Host/target platform detection
###############################################################################

# Autodetect host if necessary
ifeq ($(HOST),)
  HOST := $(shell uname -s)
endif

# Simple host sanitisation
ifeq ($(HOST),)
  # Don't ask
  HOST := riscos
else
  ifeq ($(HOST),RISC OS)
    HOST := riscos
  endif

  ifeq ($(HOST),BeOS)
    HOST := beos
  endif
  ifeq ($(HOST),Haiku)
    HOST := haiku
  endif
endif

ifeq ($(TARGET),)
  # Default target to host. Please add exceptions as required.
  TARGET := $(HOST)

  ifeq ($(HOST),haiku)
    # This isn't necessarily correct -- they have differences. However, in the 
    # general case, this will work. If there are differences that are actually 
    # important wrt the target platform (as opposed to the build host) then 
    # we'll just have to introduce a haiku target, too.
    TARGET := beos
  endif
endif

# Sanitise HOST and TARGET
# TODO: Ideally, we want the equivalent of s/[^A-Za-z0-9]/_/g here
HOST := $(subst .,_,$(subst -,_,$(subst /,_,$(HOST))))
TARGET := $(subst .,_,$(subst -,_,$(subst /,_,$(TARGET))))

# Now setup our tooling
ifeq ($(TARGET),riscos)
  ifeq ($(HOST),riscos)
    # Building on native RISC OS
    GCCSDK_INSTALL_ENV ?= <NSLibs$$Dir>

    CC__ := gcc
    CXX__ := g++
    CMHG ?= cmunge
    GENHTML ?= echo
    LCOV ?= echo
    PKGCONFIG ?=

    # This is nasty, but needed because $(CURDIR) will 
    # contain colons, and thus confuse make mightily
    $(shell SetMacro Alias$$$(COMPONENT)pwd Set %0 <FileSwitch$$CurrentFilingSystem>:|<FileSwitch$$<FileSwitch$$CurrentFilingSystem>$$CSD>|mUnset Alias$$$(COMPONENT)pwd)
    $(shell $(COMPONENT)pwd $(COMPONENT)$$Dir)
    CURDIR := <$(COMPONENT)$$Dir>
  else
    # Cross compiling for RISC OS
    GCCSDK_INSTALL_ENV ?= /home/riscos/env
    GCCSDK_INSTALL_CROSSBIN ?= /home/riscos/cross/bin

    AR__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*ar)
    CC__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*gcc)
    CXX__ := $(wildcard $(GCCSDK_INSTALL_CROSSBIN)/*g++)
    CMHG ?= PATH="$(GCCSDK_INSTALL_CROSSBIN):$(PATH)" $(GCCSDK_INSTALL_CROSSBIN)/cmunge
    GENHTML ?= echo
    LCOV ?= echo
    PKGCONFIG ?= $(GCCSDK_INSTALL_ENV)/ro-pkg-config

    ifneq ($(COMPONENT_TYPE),riscos-module)
      ifeq ($(origin CC),default)
        ifneq ($(findstring arm-unknown-riscos-gcc,$(CC__)),)
          EXEEXT := ,e1f
        else
          EXEEXT := ,ff8
        endif
      else
        ifneq ($(findstring arm-unknown-riscos-gcc,$(CC)),)
          EXEEXT := ,e1f
        else
          EXEEXT := ,ff8
        endif
      endif
    else
      EXEEXT := ,ffa
    endif
  endif

  # TODO: this assumes GCC
  CFLAGS := $(CFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include
  CXXFLAGS := $(CXXFLAGS) -mpoke-function-name -I$(GCCSDK_INSTALL_ENV)/include
  LDFLAGS := $(LDFLAGS) -L$(GCCSDK_INSTALL_ENV)/lib

  CMHGFLAGS := -p -tgcc -32bit -apcs 3/32/nonreent/fpe2/noswst/nofpr/nofp

  # Default prefix
  PREFIX ?= $(GCCSDK_INSTALL_ENV)
endif

# BeOS-like targets
ifeq ($(TARGET),beos)
  ifeq ($(HOST),beos)
    # Building on BeOS
    CC__ := gcc

    # No pkg-config
    PKGCONFIG ?=

    # Default prefix
    BEOS_INSTALL_ENV ?= /boot/home/config
  else
    ifeq ($(HOST),haiku)
      # Building on Haiku

      # Default prefix
      BEOS_INSTALL_ENV ?= /boot/common
    else
      # TODO: more sensible default
      BEOS_INSTALL_ENV ?= /home/jmb/haiku/env
      BEOS_INSTALL_CROSSBIN ?= /home/jmb/haiku/haiku/generated/cross-tools/bin

      CC__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*gcc)
      CXX__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*g++)
      AR__ := $(wildcard $(BEOS_INSTALL_CROSSBIN)/*ar)

      PKGCONFIG := PKG_CONFIG_LIBDIR="$(BEOS_INSTALL_ENV)/lib/pkgconfig:$(BEOS_INSTALL_ENV)/share/pkgconfig" pkg-config
    endif
  endif

  # TODO: this assumes GCC
  CFLAGS := $(CFLAGS) -I$(BEOS_INSTALL_ENV)/include
  CXXFLAGS := $(CXXFLAGS) -I$(BEOS_INSTALL_ENV)/include
  LDFLAGS := $(LDFLAGS) -L$(BEOS_INSTALL_ENV)/lib

  PREFIX ?= $(BEOS_INSTALL_ENV)
endif

# Windows
ifeq ($(TARGET),windows)
  ifeq ($(HOST),windows)
    $(error Compiling on Windows is not supported)
  else
    # Cross compiling for Windows -- assumes mingw toolchain
    MINGW_INSTALL_ENV ?= /usr/local/mingw

    CC__ := i586-mingw32msvc-gcc
    CXX__ := i586-mingw32msvc-g++
    AR__ := i586-mingw32msvc-ar

    PKGCONFIG ?= PKG_CONFIG_LIBDIR="$(MINGW_INSTALL_ENV)/lib/pkgconfig" pkg-config
  endif

  # TODO: this assumes GCC
  CFLAGS := $(CFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include
  CXXFLAGS := $(CXXFLAGS) -U__STRICT_ANSI__ -I$(MINGW_INSTALL_ENV)/include
  LDFLAGS := $(LDFLAGS) -L$(MINGW_INSTALL_ENV)/lib

  # Default prefix
  PREFIX ?= $(MINGW_INSTALL_ENV)
endif

###############################################################################
# Tool defaults
###############################################################################

CP ?= cp

DOXYGEN ?= doxygen

ECHO ?= echo

GENHTML ?= genhtml

ifeq ($(HOST),$(TARGET))
  HOST_CC ?= $(CC)

  HOST_CXX ?= $(CXX)
else
  HOST_CC ?= cc

  HOST_CXX ?= c++
endif

INSTALL ?= install

LCOV ?= lcov

LN ?= ln

MAKE ?= make

MKDIR ?= mkdir
MKDIRFLAGS ?= -p

MV ?= mv

PERL ?= perl

PKGCONFIG ?= pkg-config

SED ?= sed

TOUCH ?= touch

XSLTPROC ?= xsltproc

###############################################################################
# Override defaulted tools
###############################################################################

# CC
ifeq ($(findstring ccc-analyzer,$(CC)),ccc-analyzer)
    # We're being invoked by scan-build, so export 
    # the compiler we would have used such that
    # scan-build works with cross-compilation.
    # There's no need to do this if we would have
    # used the default compiler.
    ifdef CC__
      export CCC_CC := $(CC__)
    endif
else
  # Only set CC if it's not already set in the 
  # environment and we have a value for it. 
  # Otherwise, leave it to be defaulted.
  ifeq ($(origin CC),default)
    ifdef CC__
      CC := $(CC__)
    endif
  endif
endif

# CXX
ifeq ($(origin CXX),default)
  ifdef CXX__
    CXX := $(CXX__)
  endif
endif

# AR
ifeq ($(origin AR),default)
  ifdef AR__
    AR := $(AR__)
  endif
endif

###############################################################################
# Auto-detect the toolchain
###############################################################################

# Check for GCC first, as that's most likely
# TODO: Using shell redirection like this probably hurts portability
ccspecs := $(shell $(CC) -dumpspecs 2>&1)
ifeq ($(findstring libgcc,$(ccspecs)),libgcc)
  # Looks like GCC
  toolchain := gcc
else
  # Not GCC, so enquire further
  ccvsn := $(shell $(CC) --version 2>&1)
  ifeq ($(ccvsn),)
    # Version string is blank
    ifeq ($(HOST),riscos)
      # For some reason we never see the output of SCL apps, so might be
      # Norcroft.  However it might also be a GCC linked against a buggy
      # UnixLib.
      # TODO: Something more useful than blindly assuming GCC.
      ccvsn := GCC
      # ccvsn := Norcroft
    endif
  endif

  # "Norcroft ..."
  ifeq ($(word 1,$(ccvsn)),Norcroft)
    toolchain := norcroft
  endif
  # "GCC ..."
  ifeq ($(word 1,$(ccvsn)),GCC)
    toolchain := gcc
  endif
endif

ifeq ($(toolchain),)
  $(error Unable to detect toolchain)
endif

# TODO: It would be nice to avoid this hard-coded path
include build/makefiles/Makefile.$(toolchain)

###############################################################################
# Default assembler/compiler/linker/archiver flags
###############################################################################

ifeq ($(BUILD),release)
  OPTCFLAGS ?= $(CCDEF)NDEBUG $(CCOPT)
  OPTCXXFLAGS ?= $(CXXDEF)NDEBUG $(CXXOPT)
else
  OPTCFLAGS ?= $(CCDBG) $(CCNOOPT)
  OPTCXXFLAGS ?= $(CXXDBG) $(CXXNOOPT)
  OPTLDFLAGS ?= $(LDDBG)
endif

ifeq ($(origin ARFLAGS),default)
  ARFLAGS := $(ARFLG)
endif

# TODO: This assumes that the C compiler can cope with assembler
ASFLAGS ?= $(CCAS)

CFLAGS := $(CFLAGS) $(OPTCFLAGS) $(CCDEF)BUILD_TARGET_$(TARGET) $(CCDEF)BUILD_HOST_$(HOST)
CXXFLAGS := $(CXXFLAGS) $(OPTCXXFLAGS) \
		$(CXXDEF)BUILD_TARGET_$(TARGET) $(CXXDEF)BUILD_HOST_$(HOST)

ASFLAGS := $(ASFLAGS) $(CFLAGS)
LDFLAGS := $(LDFLAGS) $(OPTLDFLAGS)

###############################################################################
# lib-shared defaults
###############################################################################

# Default library extension
ifeq ($(COMPONENT_TYPE),lib-static)
  LIBEXT ?= .a
else
  LIBEXT ?= .so
endif

# If we're building a shared library, modify the flags appropriately
ifeq ($(COMPONENT_TYPE),lib-shared)
  # Default CFLAGS/LDFLAGS for shared libraries
  SHAREDCFLAGS ?= $(CCSHR) $(CCDEF)PIC
  SHAREDCXXFLAGS ?= $(CXXSHR) $(CCDEF)PIC
  SHAREDLDFLAGS ?= $(LDSHR)
  SHAREDLDPATH ?= LD_LIBRARY_PATH="$(BUILDDIR):$(LD_LIBRARY_PATH)"
endif

