# build/Common.gmake
# vi: tabstop=4
#
# Global build system setup file (for GNU Make and gcc)
#
# $Id: Common.gmake,v 1.107 2018/03/09 03:11:06 rswindell Exp $
#
#############################################################################
# @format.tab-size 4		(Plain Text/Source Code File Header)			#
# @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)			#
#																			#
# Copyright Rob Swindell - http://www.synchro.net/copyright.html			#
#																			#
# This program is free software; you can redistribute it and/or				#
# modify it under the terms of the GNU General Public License				#
# as published by the Free Software Foundation; either version 2			#
# of the License, or (at your option) any later version.					#
# See the GNU General Public License for more details: gpl.txt or			#
# http://www.fsf.org/copyleft/gpl.html										#
#																			#
# Anonymous FTP access to the most recent released source is available at	#
# ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	#
#																			#
# Anonymous CVS access to the development source and modification history	#
# is available at cvs.synchro.net:/cvsroot/sbbs, example:					#
# cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login				#
#     (just hit return, no password is necessary)							#
# cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		#
#																			#
# For Synchronet coding style and modification guidelines, see				#
# http://www.synchro.net/source.html										#
#																			#
# You are encouraged to submit any modifications (preferably in Unix diff	#
# format) via e-mail to mods@synchro.net									#
#																			#
# Note: If this box doesn't appear square, then you need to fix your tabs.	#
#############################################################################
#																			#
#############################################################################
#																			#
# Common macro setup for GNU make											#
#																			#
# Common Build Macros REQUIRED:												#
#  SRC_ROOT			- *MUST* be set to the src dir							#
#  3RDP_ROOT		- If not set, defaults to $(SRC_ROOT)/../3rdp			#
#																			#
# Common Build Macros Used:													#
#  DEBUG			- Create a debug build									#
#  PROFILE			- Generates binaries which generate gprof details		#
#					  (GCC/DEBUG only)										#
#  UPROFILE			- Generates binaries which generate profile-driven		#
#					  optimization data										#
#					  (GCC/DEBUG only)										#
#  GCOV				- Generates binaries that produce gcov data				#
#					  (GCC/DEBUG only)										#
#  RELEASE			- Create a release build								#
#					  (Mutually exclusive, if both are set, RELEASE 		#
#						is cleared)											#
#  USE_UPROFILE		- Builds using information generated by UPROFILE.		#
#					  (RELEASE builds only)									#
#  OBJPATH_SUFFIX	- Suffix appended to OBJPATH useful for compiling 		#
#					  different options of the same source file				#
#  STATIC			- Create a statically linked build if possible			#
#																			#
# Common Build Macros Defined:												#
#  DELETE			- Delete files (Preferrably verbose)					#
#  MTOBJODIR		- Object output dir										#
#  OBJODIR			- Object output dir										#
#  LIBODIR			- Library output dir									#
#  EXEODIR			- Executable output dir									#
#  DEBUG			- Set for debug builds									#
#  RELEASE			- Set for release builds								#
#					  One of DEBUG or RELEASE is always set!				#
#  QUIET			- Target command prefix to show/not show commands		#
#  					  (Toggled off by setting VERBOSE)						#
#  CFLAGS			- Common C and C++ compiler flags						#
#  CCFLAGS			- C specific compiler flags								#
#  CXXFLAGS			- C++ specific compiler flags							#
#  LDFLAGS			- Linker flags											#
#  CC				- C compiler											#
#  CXX				- C++ compiler											#
#  EXEFILE			- Executable file extension (Includes .)				#
#  OFILE			- Object file extension (Includes .)					#
#  SOFILE			- Shared object (DLL) file extension (Includes .)		#
#  LIBFILE			- Static library file extension (Include .)				#
#  LIBPREFIX		- Prefix to library filename							#
#  LIBS				- Library names	(Appropriate for dependencies)			#
#  LIB_LDFLAGS		- Libraries appropriate for link command-line usage		#
#  COMPILE_MSG		- Message saying a target is being compiled				#
#  DIRSEP			- The directory seperator this system likes most		#
#  VERSION			- Synchronet version number in MAJOR.MINOR format		#
#					  (Numeric ONLY)										#
#  OUTPUT			- Compiler flag specifying output filename				#
#  LOUTPUT			- Linker flag specifying output filename				#
#  XPDEV_SRC		- Path to xpdev											#
#  UIFC_SRC			- Path to uifc											#
#  CIOLIB_SRC		- Path to ciolib										#
#  SMBLIB_SRC		- Path to smblib										#
#  MT_CFLAGS		- CFLAGS for building MT objects						#
#  MT_LDFLAGS		- LDFLAGS for linking MT targets						#
#  UL_PRE			- Use Library prefix (*nix is -l)						#
#  UL_SUF			- Use Library siffix (bcc is .lib)						#
#																			#
# Common Targets Defined:													#
#  Implicit C and C++ targets												#
#  "clean" target															#
#  Output directory targets													#
#																			#
#############################################################################

# Set SBBSEXEC (if SBBSCTRL is set)
ifdef SBBSCTRL
ifndef SBBSEXEC
SBBSEXEC:=$(SBBSCTRL)/../exec
endif
endif

# Set VERSION
ifndef VERSION
 VERSION	:=	3.17
endif

# Put local (optional) macro definitions in localdefs.mk
-include localdefs.mk
-include $(SRC_ROOT)/build/localdefs.mk

# Set DEBUG
ifdef DEBUG
 ifdef RELEASE
  $(error Both DEBUG and RELEASE are defined)
 endif
endif

ifndef DEBUG
 ifndef RELEASE
  DEBUG	:=	1
 endif
endif

ifdef DEBUG
 ifdef PROFILE
  CFLAGS	+=	-pg
  LDFLAGS	+=	-pg
 endif
 ifdef UPROFILE
  CFLAGS	+=	-fprofile-generate
  LDFLAGS	+=	-fprofile-generate
 endif
 ifdef GCOV
  CFLAGS	+=	-fprofile-arcs -ftest-coverage
  LDFLAGS	+=	-fprofile-arcs -ftest-coverage
 endif
else
 ifdef USE_UPROFILE
  CFLAGS	+=	-fprofile-use
  LDFLAGS	+=	-fprofile-use
 endif
endif

# VERBOSE/QUIET
ifndef VERBOSE
 QUIET	:=	@
endif

# Compiler-specific options
CFLAGS	+=	-MMD
CC		?=	gcc
CCPRE	?= ${shell if [ `echo __clang__ | $(CC) -E - | grep -v '^\#'` != __clang__ ] ; then echo clang ; elif [ `echo __INTEL_COMPILER | $(CC) -E - | grep -v '^\#'` != __INTEL_COMPILER ] ; then echo icc ; else echo gcc ; fi}
ifeq ($(CCPRE),clang)
 ifeq ($(CC),cc)
  CXX	:=	c++
 else
  ifeq ($(CC),clang)
   CXX	:=	clang++
  endif
 endif
endif
ifdef BUILD_DEPENDS
 CC				:=	$(SRC_ROOT)/build/mkdep -a
 CXX			:=	$(SRC_ROOT)/build/mkdep -a
 LD				:=	echo
 COMPILE_MSG	:=  Depending
 AR				:=	echo
 RANLIB			:=	echo
else
 CXX			?=	g++
 LD				?=	ld
 COMPILE_MSG	:= Compiling
 AR				?=	ar
 RANLIB			?=	ranlib
endif
WINDRES	?=	windres

ifdef DEBUG
 BUILD	=	debug
else
 BUILD	=	release
endif
BUILDPATH	?=	$(BUILD)

gcc_machine		:= $(shell ${CC} -dumpmachine)
ifeq ($(gcc_machine),mingw32)
 os		:= Win32
 CFLAGS	+=	-DMSVCRT_VERSION=0x0800
endif

# Get OS
ifndef os
 os		:=	$(shell uname)
endif
os      :=	$(shell echo $(os) | tr '[A-Z]' '[a-z]' | tr ' ' '_')

machine		:=	$(shell if uname -m | egrep -v "(i[3456789]*|x)86" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; fi)
machine		:=	$(shell if uname -m | egrep "64" > /dev/null; then uname -m | tr "[A-Z]" "[a-z]" | tr " " "_" ; else echo $(machine) ; fi)
ifeq ($(os),darwin)
 ifeq ("$(machine)","")
  ifeq ($(shell sysctl hw.optional.x86_64),hw.optional.x86_64: 1)
   machine	:= x86_64
  endif
 endif
endif

ifeq ($(machine),x86_64)
 machine	:= x64
endif
CFLAGS +=	-fpic
ifeq ($(machine),sparc64)
 CFLAGS +=      -D__BIG_ENDIAN__
endif
ifeq ($(machine),sun4u)
 CFLAGS +=      -D__BIG_ENDIAN__
endif
ifeq ($(machine),power_macintosh)
 CFLAGS +=      -D__BIG_ENDIAN__
endif
ifeq ($(machine),mac68k)
 CFLAGS +=      -D__BIG_ENDIAN__
endif
ifeq ($(machine),)
 machine	:=	$(os)
else
 machine	:=	$(os).$(machine)
endif

ifeq ($(shell if [ -f /usr/include/inttypes.h ] ; then echo YES ; fi),YES)
 CFLAGS	+=	-DHAS_INTTYPES_H
else
 ifeq ($(shell if [ -f /boot/develop/headers/posix/inttypes.h ] ; then echo YES ; fi),YES)
  CFLAGS	+=	-DHAS_INTTYPES_H
 else
  ifeq ($(os),darwin)	# Don't go digging for stuff on Mac, nobody knows what's up.
   CFLAGS	+=	-DHAS_INTTYPES_H
  endif
 endif
endif

CCPRE := $(lastword $(subst /, ,$(CCPRE)))
ifeq ($(CCPRE),clang)
 CFLAGS += -Wno-invalid-source-encoding
endif
LIBODIR :=	$(CCPRE).$(machine).lib.$(BUILDPATH)
OBJODIR :=	$(CCPRE).$(machine).obj.$(BUILDPATH)
MTOBJODIR :=	$(CCPRE).$(machine).obj.$(BUILDPATH)-mt
EXEODIR :=	$(CCPRE).$(machine).exe.$(BUILDPATH)
LDFLAGS	+=	-L$(LIBODIR)

ifeq ($(os),openbsd)
 DELETE :=	rm -f
else
 ifeq ($(os),sunos)
  DELETE :=	rm -f
 else
  DELETE	=	rm -f
 endif
endif

LIBPREFIX	:= lib
DIRSEP		:= /
OFILE		:= .o
ifeq ($(os),win32)
 EXEFILE		:= .exe
else
 EXEFILE		:=
endif
SOFILE		:= .so
LIBFILE		:= .a
UL_PRE		:=	-l
UL_SUF		:=	

OUTPUT		:=	-o
LOUTPUT		:=	-o

ifdef STATIC
 LDFLAGS	+=	-static
 CFLAGS		+=	-DSTATIC_LINK
endif

ifeq ($(os),openbsd)
 SOFILE	:=	$(SOFILE).$(VERSION)
else
 ifeq ($(os),darwin)
  SOFILE =	.dylib
  RANLIB +=	-s
 endif
endif

# OS Specific Flags
ifeq ($(os),sunos)    # Solaris CFLAGS	+= -D__solaris__ -DNEEDS_DAEMON -DNEEDS_FORKPTY -DNEEDS_CFMAKERAW # Solaris 10 provides setenv()
 ifeq ($(shell if [ `uname -r | sed 's/\.//'` -lt 510 ] ; then echo "Yes" ; else echo "No" ; fi),Yes)
  CFLAGS += -DNEEDS_SETENV
 endif
 LDFLAGS	+=	-L/opt/sfw/lib
endif
ifeq ($(os),netbsd)	# NetBSD
 CFLAGS	+=	-D__unix__ -I/usr/pkg/include
endif
ifeq ($(os),haiku)
 CFLAGS	+=	-D__unix__ -DNEEDS_FORKPTY
endif
ifeq ($(os),darwin)
 CFLAGS +=  -D__unix__ -fno-common -D__DARWIN__
endif

# PThread-specific flags
ifeq ($(os),linux)    # Linux
 CFLAGS	+=	-DPOSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -DSPEED_MACROS_ONLY -D_GNU_SOURCE
 ifndef THREADS_ACTUALLY_WORK
  CFLAGS    += -D_THREAD_SUID_BROKEN
 endif
endif
MT_CFLAGS    += -D_THREAD_SAFE -D_REENTRANT
ifeq ($(os),freebsd)    # FreeBSD
 MT_CFLAGS    += -DUSE_XP_SEMAPHORES
 MT_LDFLAGS    +=    -pthread
 LDFLAGS    +=    -pthread
 XP_SEM    :=    1
else
 ifeq ($(os),openbsd)    # OpenBSD
  MT_CFLAGS    += -DUSE_XP_SEMAPHORES
  MT_LDFLAGS    +=    -pthread
  LDFLAGS    +=    -pthread
  XP_SEM    :=    1
 else
  ifeq ($(os),netbsd)    # NetBSD
   MT_CFLAGS	+=	-DUSE_XP_SEMAPHORES
   MT_LDFLAGS    +=   -L/usr/pkg/lib
   XP_SEM    :=    1
  else
   ifeq ($(os),qnx)    # QNX
   else
    ifeq ($(os),darwin)    # Darwin/Mac OS X
     CFLAGS    += -D__unix__ 
     MT_CFLAGS    += -DUSE_XP_SEMAPHORES -D__DARWIN__
     XP_SEM    := 1
    else
     ifeq ($(os),sunos)  # Solaris
      XP_SEM :=    1
      MT_CFLAGS    +=    -D_POSIX_PTHREAD_SEMANTICS
      MT_CFLAGS    += -DUSE_XP_SEMAPHORES
      # This makes ctime_r() be the correct one.
      #CFLAGS	   += -D_POSIX_PTHREAD_SEMANTICS
     else
      ifeq ($(os),win32) # Windows
       CFLAGS		+= -U__STRICT_ANSI__ -D_WIN32 -D_WIN32_WINNT=0x0501 -DWINVER=0x0501 -D_WIN32_IE=0x0500
       MT_CFLAGS	+= -D_WIN32
      else           # Linux / Other UNIX
       XP_SEM :=    1
       MT_CFLAGS    += -DUSE_XP_SEMAPHORES
      endif
     endif
    endif
   endif
  endif
 endif
endif

SHLIBOPTS   :=  -shared
ifeq ($(os),darwin)
 MKSHLIB        :=  libtool -dynamic -framework System -lcc_dynamic
 MKSHPPLIB      :=  libtool -dynamic -framework System -lcc_dynamic -lstdc++
 SHLIBOPTS  :=
else
 ifeq ($(os),sunos)
  MKSHLIB       :=  /usr/ccs/bin/ld -G
  MKSHPPLIB     :=  /usr/ccs/bin/ld -G
  SHLIBOPTS :=
 else
  MKSHLIB       :=  $(CC)
  MKSHPPLIB     :=  $(CXX)
 endif
endif

# Paths
XPDEV_SRC	:=	$(SRC_ROOT)$(DIRSEP)xpdev
CIOLIB_SRC	:=	$(SRC_ROOT)$(DIRSEP)conio
SMBLIB_SRC	:=	$(SRC_ROOT)$(DIRSEP)smblib
UIFC_SRC	:=	$(SRC_ROOT)$(DIRSEP)uifc
3RDP_ROOT	?=	$(SRC_ROOT)$(DIRSEP)..$(DIRSEP)3rdp
3RDP_BUILD	:=	$(3RDP_ROOT)$(DIRSEP)build

# SDL ciolib enabled by default for the moment.
ifndef WITHOUT_SDL
 ifndef USE_SDL_AUDIO
  USE_SDL	:=	1
 endif
endif

# Pull in lib-specific flags
-include		$(XPDEV_SRC)$(DIRSEP)Common.make
-include		$(XPDEV_SRC)$(DIRSEP)Common.gmake
-include		$(SMBLIB_SRC)$(DIRSEP)Common.make
-include		$(SMBLIB_SRC)$(DIRSEP)Common.gmake
-include		$(CIOLIB_SRC)$(DIRSEP)Common.make
-include		$(CIOLIB_SRC)$(DIRSEP)Common.gmake
-include		$(UIFC_SRC)$(DIRSEP)Common.make
-include		$(UIFC_SRC)$(DIRSEP)Common.gmake
-include		$(3RDP_BUILD)$(DIRSEP)Common.make
-include		$(3RDP_BUILD)$(DIRSEP)Common.gmake

ifdef DEBUG
 CFLAGS	+=	-ggdb
 CFLAGS	+=	-D_DEBUG
 CFLAGS +=	-Wall -Wno-char-subscripts
else # RELEASE
 # -finline functions breaks the baja build badly.
 # This also means that -O3 won't work either.
 CFLAGS	:= -O2 -fomit-frame-pointer -ffast-math -funroll-loops $(CFLAGS)
endif

-include targets.mk
-include $(SRC_ROOT)/build/rules.mk
-include objects.mk		# defines $(OBJS)

# Implicit C Compile Rule
$(OBJODIR)/%$(OFILE) : %.c $(BUILD_DEPENDS) | $(OBJODIR)
	@echo $(COMPILE_MSG) $<
	$(QUIET)$(CC) -std=c99 $(CFLAGS) $(CCFLAGS) -o $@ -c $<

# Implicit C++ Compile Rule
$(OBJODIR)/%$(OFILE) : %.cpp $(BUILD_DEPENDS) | $(OBJODIR)
	@echo $(COMPILE_MSG) $<
	$(QUIET)$(CXX) $(CFLAGS) $(CXXFLAGS) -o $@ -c $<

# Implicit MT C Compile Rule
$(MTOBJODIR)/%$(OFILE) : %.c $(BUILD_DEPENDS) | $(MTOBJODIR)
	@echo $(COMPILE_MSG) $<
	$(QUIET)$(CC) -std=c99 $(CFLAGS) $(CCFLAGS) $(MT_CFLAGS) -o $@ -c $<

# Implicit MT C++ Compile Rule
$(MTOBJODIR)/%$(OFILE) : %.cpp $(BUILD_DEPENDS) | $(MTOBJODIR)
	@echo $(COMPILE_MSG) $<
	$(QUIET)$(CXX) $(CFLAGS) $(CXXFLAGS) $(MT_CFLAGS) -o $@ -c $<

depend:
	$(QUIET)$(DELETE) $(OBJODIR)/.depend
	$(QUIET)$(DELETE) $(MTOBJODIR)/.depend
	$(QUIET)$(DELETE) $(LIBODIR)/.depend
	$(QUIET)$(DELETE) $(EXEODIR)/.depend
	$(QUIET)$(MAKE) BUILD_DEPENDS=FORCE

FORCE:

-include $(MTOBJODIR)/.depend
-include $(OBJODIR)/.depend
-include $(LIBODIR)/.depend
-include $(EXEODIR)/.depend
-include $(MTOBJODIR)/*.d
-include $(OBJODIR)/*.d
-include $(LIBODIR)/*.d
-include $(EXEODIR)/*.d

$(XPDEV_LIB): xpdev
xpdev:
	$(MAKE) -C $(XPDEV_SRC) lib

$(XPDEV-MT_LIB): xpdev-mt
xpdev-mt:
	$(MAKE) -C $(XPDEV_SRC) mtlib

$(SMBLIB): smblib
smblib:
	$(MAKE) -C $(SMBLIB_SRC) lib

$(CIOLIB-MT): ciolib-mt
ciolib-mt:
	$(MAKE) -C $(CIOLIB_SRC) mtlib

$(UIFCLIB): uifc
uifc:
	$(MAKE) -C $(UIFC_SRC) lib

$(UIFCLIB-MT): uifc-mt
uifc-mt:
	$(MAKE) -C $(UIFC_SRC) mtlib

$(JS_LIB):  $(JS_DEPS)
js:
	$(MAKE) -C $(3RDPBUILDDIR) jslib

$(CRYPT_LIB):  $(CRYPT_DEPS)
cl:
	$(MAKE) -C $(3RDPBUILDDIR) cryptlib
