# NMakefile for libNymphCast
#
# Build and install libNymphCast static library (MSVC).
#
# Created 17 October 2021.
# Copyright (c) 2021 Nyanko.ws
#
# Usage: nmake -f NMakefile [definitions] [target]
#
# Definitions:
# - NC_STATIC={0|1}
# - NC_CONFIG={Debug|Release}
# - NC_CPPSTD={flag}
# - NC_LNKCRT={flag}
# - NC_WARNING={flag}
# - NC_OPTIMIZATION={flag}
# - POCO_ROOT={install-folder}]
# - NYMPHRPC_ROOT={install-folder}
# - LIBNYMPHCAST_ROOT={install-folder}
# - INSTALL_PREFIX={install-folder}
#
# Targets:
# - all
# - lib, same as all
# - install
# - clean
# - dist-clean
# - real-clean, same as dist-clean
#
# Configuration:
# - `NC_CONFIG` defaults to `Release`.
# - `NC_CPPSTD` defaults to `-std:c++latest`.
# - `NC_LNKCRT` defaults to `-MD`.
# - `NC_WARNING` defaults to empty, default compiler behaviour.
# - `NC_OPTIMIZATION` defaults to `-Od` for Debug, `-O2` for Release.
# - `INSTALL_PREFIX` defaults to `$(LIBNYMPHCAST_ROOT)`
# - If defined, environment variable `POCO_ROOT` is used for Poco dependency [D:\Libraries\Poco].
# - If defined, environment variable `NYMPHRPC_ROOT` is used for NymphRPC dependency [D:\Libraries\NymphRPC].
# - If defined, environment variable `LIBNYMPHCAST_ROOT` is used for LibNymphCast dependency [D:\Libraries\LibNymphCast].
#
# Dependencies:
# - Nymph: NymphRPC
# - Poco: PocoFoundation, PocoNet, https://pocoproject.org/
#
# Installation destination:
# - `NYMPHRPC_ROOT`
# - e.g.: `set NYMPHRPC_ROOT=C:\Libraries\libNymphCast`
#
# Product build directories:
# - .\lib\x86_{32|64}-w64-msvc\{Debug|Release}
# - .\obj\static\x86_{32|64}-w64-msvc\{Debug|Release}
#
# Use the Microsoft C++ toolset from the command line.
# https://docs.microsoft.com/en-us/cpp/build/building-on-the-command-line?view=msvc-160
#

# Configuration:

# Note: no space before macro being defined.

!ifdef NC_STATIC
LIB_STATIC = $(NC_STATIC)
!else
LIB_STATIC = 0
!endif

!ifdef NC_CONFIG
LIB_CONFIG = $(NC_CONFIG)
!else
LIB_CONFIG = Release
!endif

LIB_DEF_CPPSTD = -std:c++latest

!ifdef NC_CPPSTD
LIB_CPPSTD = $(NC_CPPSTD)
!else
LIB_CPPSTD = $(LIB_DEF_CPPSTD)
!endif

LIB_DEF_LNKCRT = -MD

!ifdef NC_LNKCRT
LIB_LNKCRT = $(NC_LNKCRT)
!else
LIB_LNKCRT = $(LIB_DEF_LNKCRT)
!endif

!if "$(LIB_LNKCRT)" == "-MT"
LIB_LNKCRT_MT = mt
!else
LIB_LNKCRT_MT =
!endif

!ifndef POCO_ROOT
POCO_ROOT = D:\Libraries\Poco
!endif

!ifndef NYMPHRPC_ROOT
NYMPHRPC_ROOT = D:\Libraries\NymphRPC
!endif

!ifndef LIBNYMPHCAST_ROOT
LIBNYMPHCAST_ROOT = D:\Libraries\LibNymphCast
!endif

!ifndef INSTALL_PREFIX
INSTALL_PREFIX = $(LIBNYMPHCAST_ROOT)
!endif

!ifdef NC_OPTIMIZATION
LIB_OPTIMIZATION = $(NC_OPTIMIZATION)
!elseif "$(LIB_CONFIG)" == "Release"
LIB_OPTIMIZATION = -O2
!else
LIB_OPTIMIZATION = -Od
!endif

!ifdef NC_WARNING
LIB_WARNING = $(NC_WARNING)
!else
LIB_WARNING =	# Use default warning level
!endif

# End Configuration.

# Determine 32, or 64 bit:

!if "$(VSCMD_ARG_TGT_ARCH)" == "x86"
LIB_BITS = 32
!elseif "$(VSCMD_ARG_TGT_ARCH)" == "x64"
LIB_BITS = 64
!else
!error [Got unexpected target architecture '$(VSCMD_ARG_TGT_ARCH)'. Bailing out.]
!endif

# Sanity checks:

!if "$(LIB_CONFIG)" != "Debug" && "$(LIB_CONFIG)" != "Release"
!error [Expecting 'CONFIG=Debug' or 'CONFIG=Release', got 'CONFIG=$(LIB_CONFIG)'. Bailing out.]
!endif

!if !exist("$(POCO_ROOT)\include\Poco\Poco.h")
!error [Cannot find Poco dependency at '$(POCO_ROOT)'. Bailing out.]
!endif

!if !exist("$(NYMPHRPC_ROOT)\include\nymph\nymph.h")
!error [Cannot find NymphRPC dependency at '$(NYMPHRPC_ROOT)'. Bailing out.]
!endif

# INACTIVE: Setup desired toolset ()
# Note: did not get this to work; use the NMake from the cmd for the desired toolset.

# !if ["$(VCINSTALLDIR)\Auxiliary\Build\vcvars$(LIB_BITS).bat" ]
# !endif
# Commands:

CXX   = cl -nologo
LIB   = lib -nologo

CP    = xcopy /Y
RM    = del
MKDIR = md		# Note: Do not use MAKEDIR=... as MAKEDIR is an NMake macro.

# Product-related macros:

LIB_OUTPUT  = NymphCast$(LIB_LNKCRT_MT).lib

SRC_FOLDER  = src
#LIB_ARCH   = $(VSCMD_ARG_TGT_ARCH)_$(LIB_BITS)-w64-msvc	# e.g.: x86_32-w64-msvc
LIB_ARCH    = x86_$(LIB_BITS)-w64-msvc				# e.g.: x86_32-w64-msvc
LIB_FOLDER  = lib/$(LIB_ARCH)/$(LIB_CONFIG)			# e.g.: lib\x86_32-w64-msvc\Release
OBJ_FOLDER  = obj/static/$(LIB_ARCH)/$(LIB_CONFIG)	# e.g.: obj\static\x86_32-w64-msvc\Release

LIB_INCLUDE = \
	-I "$(SRC_FOLDER)" \
	-I "$(NYMPHRPC_ROOT)/include" \
	-I "$(POCO_ROOT)/include"

# libraries to link to when using LibNymphCast:

LIB_LIBS  = \
    NymphRPC$(LIB_LNKCRT_MT).lib \
    PocoFoundation$(LIB_LNKCRT_MT).lib \
    PocoNet$(LIB_LNKCRT_MT).lib \
    PocoUtil$(LIB_LNKCRT_MT).lib \
	Ws2_32.lib \
	iphlpapi.lib

!if $(LIB_STATIC) != 0
LIB_DEFS_STATIC = -DPOCO_STATIC
!else
LIB_DEFS_STATIC =
!endif

LIB_FLAGS = # -Zc:strictStrings-
LIB_DEFS  = $(LIB_DEFS_STATIC)
CXXFLAGS  = $(LIB_CPPSTD) -EHsc -Zi -MP $(LIB_LNKCRT) $(LIB_FLAGS) $(LIB_WARNING) $(LIB_OPTIMIZATION) $(LIB_DEFS) $(LIB_INCLUDE)

INST_FOLDER_INC = $(INSTALL_PREFIX)\include
INST_FOLDER_LIB = $(INSTALL_PREFIX)\lib

# Create targets:

LIB_SOURCES_DIR = \
	$(SRC_FOLDER)/bytebauble.cpp \
	$(SRC_FOLDER)/nyansd.cpp \
	$(SRC_FOLDER)/nymphcast_client.cpp

# Two steps:

LIB_OBJECTS_TMP = $(LIB_SOURCES_DIR:.cpp=.obj)

# LIB_OBJECTS_DIR = $(LIB_OBJECTS_TMP:src/=$(OBJ_FOLDER)/)	# <== This seems to not work.

# TODO ./ => src
# Write-out all permutations:

!if     "$(LIB_BITS)" == "32" && "$(LIB_CONFIG)" == "Debug"
LIB_OBJECTS_DIR = $(LIB_OBJECTS_TMP:src/=obj/static/x86_32-w64-msvc/Debug/)
!elseif "$(LIB_BITS)" == "32" && "$(LIB_CONFIG)" == "Release"
LIB_OBJECTS_DIR = $(LIB_OBJECTS_TMP:src/=obj/static/x86_32-w64-msvc/Release/)
!elseif "$(LIB_BITS)" == "64" && "$(LIB_CONFIG)" == "Debug"
LIB_OBJECTS_DIR = $(LIB_OBJECTS_TMP:src/=obj/static/x86_64-w64-msvc/Debug/)
!elseif "$(LIB_BITS)" == "64" && "$(LIB_CONFIG)" == "Release"
LIB_OBJECTS_DIR = $(LIB_OBJECTS_TMP:src/=obj/static/x86_64-w64-msvc/Release/)
!endif

#
# Inference rules:
#

{$(SRC_FOLDER)/}.cpp{$(OBJ_FOLDER)/}.obj:
	$(CXX) -c $(CXXFLAGS) -Fo$@ $<

#
# Targets:
#

all: print-configuration lib

# Quote echo text to keep alignment:

print-configuration:
	@echo.
	@echo Building static library '$(LIB_OUTPUT)' with Configuration:
	@echo "- LIB_STATIC      : '$(LIB_STATIC)'"
	@echo "- LIB_CONFIG      : '$(LIB_CONFIG)'"
	@echo "- LIB_BITS        : '$(LIB_BITS)'"
	@echo "- LIB_CPPSTD      : '$(LIB_CPPSTD)'"
	@echo "- LIB_WARNING     : '$(LIB_WARNING)'"
	@echo "- LIB_OPTIMIZATION: '$(LIB_OPTIMIZATION)'"
	@echo "- LIB_LNKCRT      : '$(LIB_LNKCRT)'"
	@echo "- LIB_FOLDER      : '$(LIB_FOLDER)'"
	@echo "- OBJ_FOLDER      : '$(OBJ_FOLDER)'"
	@echo "- POCO_ROOT       : '$(POCO_ROOT)'"
	@echo "- NYMPHRPC_ROOT   : '$(NYMPHRPC_ROOT)'"
	@echo "- INSTALL_PREFIX  : '$(INSTALL_PREFIX)'"
	@echo.
	@echo "- sources: $(LIB_SOURCES_DIR)"
	@echo "- objects: $(LIB_OBJECTS_DIR)"
	@echo.

lib: makedir-lib $(LIB_FOLDER)\$(LIB_OUTPUT)

makedir-lib:
	-$(MKDIR) "$(LIB_FOLDER)" > nul 2>&1
	-$(MKDIR) "$(OBJ_FOLDER)" > nul 2>&1

# Dependencies:

$(LIB_OBJECTS_DIR): $(LIB_SOURCES_DIR)

$(LIB_FOLDER)\$(LIB_OUTPUT): $(LIB_OBJECTS_DIR)
	$(LIB) -out:$(LIB_FOLDER)\$(LIB_OUTPUT) $(LIB_OBJECTS_DIR)

# Installation targets:

install: lib makedir-install copy-install

makedir-install:
	-$(MKDIR) "$(INST_FOLDER_INC:/=\)" > nul 2>&1
	-$(MKDIR) "$(INST_FOLDER_LIB:/=\)" > nul 2>&1

copy-install:
	$(CP) "$(SRC_FOLDER:/=\)\*.h" "$(INST_FOLDER_INC:/=\)\"
	$(CP) "$(LIB_FOLDER:/=\)\$(LIB_OUTPUT)" "$(INST_FOLDER_LIB:/=\)\"

# Clean targets:

clean:
	-$(RM) $(OBJ_FOLDER:/=\)\*.obj

dist-clean: clean
	-$(RM) $(LIB_FOLDER:/=\)\$(LIB_OUTPUT)

real-clean: dist-clean

# end of file
