# Copyright (C) The c-ares project and its contributors
# SPDX-License-Identifier: MIT
#
# Permission to use, copy, modify, and distribute this
# software and its documentation for any purpose and without
# fee is hereby granted, provided that the above copyright
# notice appear in all copies and that both that copyright
# notice and this permission notice appear in supporting
# documentation, and that the name of M.I.T. not be used in
# advertising or publicity pertaining to distribution of the
# software without specific, written prior permission.
# M.I.T. makes no representations about the suitability of
# this software for any purpose.  It is provided "as is"
# without express or implied warranty.

# ------------------------------------------------------------------------------
#
# Makefile for building c-ares test suite with MSVC.
#
# Usage: nmake /f makefile.msvc CFG=<config> <target>
#
# <config> can be one of: [ lib-release | lib-debug | dll-release | dll-debug }
# <target> can be one of: [ all | arestest | clean }
#
# If <target> is not specified then all targets are built.
# If <config> is not specified then lib-debug will be assumed.
#
# This makefile must be processed from the subdir where it is located.
#
# All results are generated below a subdirectory named msvcXXX.
#
# ------------------------------------------------------------------------------


# ------------------------------------------------
# c-ares static and dynamic libraries common base
# file names for release and debug configurations
# ------------------------------------------------

LIBNAME = cares
STA_LIB_REL = lib$(LIBNAME)
DYN_LIB_REL = $(LIBNAME)
STA_LIB_DBG = $(STA_LIB_REL)d
DYN_LIB_DBG = $(DYN_LIB_REL)d

# -------------------------------------------
# Base names for c-ares DLL import libraries
# -------------------------------------------

IMP_LIB_REL = $(DYN_LIB_REL)
IMP_LIB_DBG = $(DYN_LIB_DBG)

# --------------------------
# Runtime library selection
# --------------------------

RTLIB  = /MD
RTLIBD = /MDd

!IF "$(RTLIBCFG)" == "static"
RTLIB  = /MT
RTLIBD = /MTd
!ENDIF

# --------------------------------------------------------
# Detect compiler version.
# --------------------------------------------------------
!INCLUDE ..\msvc_ver.inc

# ---------------------------------------------------------
# Verify that current subdir is below the c-ares source one
# ---------------------------------------------------------

!IF ! EXIST(..\src\lib\ares_init.c)
!  MESSAGE Can not process Makefile.msvc from outside of c-ares test subdirectory.
!  MESSAGE Change to the subdirectory where Makefile.msvc is found, and try again.
!  ERROR   See previous message.
!ENDIF

# ------------------------------------------------------------------
# Base subdir is the common root from which other subdirs will hang,
# the name depends on MSVC version being used when building c-ares.
# ------------------------------------------------------------------

BASE_DIR = .\msvc
# Look for a built library of the same configuration in the directory above.
LIB_BASE_DIR = ..\msvc

# ----------------------------------------
# Subdir holding sources for all projects
# ----------------------------------------

SRCDIR = .

# -------------------------
# Configuration validation
# -------------------------

!IF "$(CFG)" == ""
CFG = lib-debug
!ENDIF

VALID_CFGSET = FALSE
!IF "$(CFG)" == "lib-release" || "$(CFG)" == "lib-debug" || \
    "$(CFG)" == "dll-release" || "$(CFG)" == "dll-debug"
VALID_CFGSET = TRUE
!ENDIF

!IF "$(VALID_CFGSET)" == "FALSE"
!  MESSAGE MSVC c-ares makefile
!  MESSAGE
!  MESSAGE Usage: nmake /f makefile.msvc CFG=<config> <target>
!  MESSAGE
!  MESSAGE <config> can be one of: [ lib-release | lib-debug | dll-release | dll-debug }
!  MESSAGE <target> can be one of: [ all | arestest | aresfuzz | aresfuzzname | dnsdump | clean }
!  MESSAGE
!  MESSAGE If <target> is not specified then all targets are built.
!  MESSAGE If <config> is not specified then lib-debug will be assumed.
!  MESSAGE
!  ERROR Choose a valid configuration.
!ENDIF

# --------------------------------------------------------
# Project subdirs independent of configuration being used
# --------------------------------------------------------

PROG_DIR = $(BASE_DIR)\arestest
LIB_DIR = $(LIB_BASE_DIR)\cares

GMOCK_DIR = gmock-1.11.0

# ---------------------------------------------------
# Subdirs which are configuration dependent are only
# defined when a valid configuration has been given.
# ---------------------------------------------------

PROG_OUTDIR = $(PROG_DIR)\$(CFG)
PROG_OBJDIR = $(PROG_OUTDIR)\obj
LIB_OUTDIR = $(LIB_DIR)\$(CFG)


# -------------------------------------
# TCP/IP stack settings
# -------------------------------------
CFLAGS  = /DWIN32
EX_LIBS_REL = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib
EX_LIBS_DBG = ws2_32.lib advapi32.lib kernel32.lib iphlpapi.lib

# -------------------------------------------------
# Switches that depend on ancient compiler versions
# -------------------------------------------------

!IF $(CC_VERS_NUM) == 60
PDB_NONE            = /pdb:none
PDBTYPE_CONSOLIDATE = /pdbtype:consolidate
!ELSE
!UNDEF PDB_NONE
!UNDEF PDBTYPE_CONSOLIDATE
!ENDIF

!IF $(CC_VERS_NUM) <= 70
RT_ERROR_CHECKING = /GZ
!ELSE
RT_ERROR_CHECKING = /RTCsu
!ENDIF

# ----------------------------
# Assorted commands and flags
# ----------------------------

CC_CMD_REL = cl.exe /nologo $(RTLIB) /DNDEBUG /O2 /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS
CC_CMD_DBG = cl.exe /nologo $(RTLIBD) /D_DEBUG /Od /Zi /D_CRT_NONSTDC_NO_DEPRECATE /D_CRT_SECURE_NO_WARNINGS $(RT_ERROR_CHECKING)
CC_CFLAGS  = $(CFLAGS) /I. /I../src/lib /I../include /I $(GMOCK_DIR) /W3 /EHsc /FD

RC_CMD_REL = rc.exe /l 0x409 /d "NDEBUG"
RC_CMD_DBG = rc.exe /l 0x409 /d "_DEBUG"

LINK_CMD_LIB = link.exe /lib /nologo
LINK_CMD_DLL = link.exe /dll /nologo /incremental:no /fixed:no
LINK_CMD_EXE = link.exe /nologo /incremental:no /fixed:no /subsystem:console

LINK_CMD_EXE_REL = $(LINK_CMD_EXE) /release $(PDB_NONE)
LINK_CMD_EXE_DBG = $(LINK_CMD_EXE) /debug $(PDBTYPE_CONSOLIDATE)

# ---------------------------------
# Configuration dependent settings
# ---------------------------------

!IF "$(CFG)" == "lib-release"
CARES_TARGET = $(STA_LIB_REL).lib
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB
CARES_LFLAGS =
SPROG_CFLAGS = /DCARES_STATICLIB
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_REL) $(STA_LIB_REL).lib
CARES_LINK   = $(LINK_CMD_LIB)
SPROG_LINK   = $(LINK_CMD_EXE_REL)
CC_CMD       = $(CC_CMD_REL)
!ENDIF

!IF "$(CFG)" == "lib-debug"
CARES_TARGET = $(STA_LIB_DBG).lib
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DCARES_STATICLIB /DDEBUGBUILD
CARES_LFLAGS =
SPROG_CFLAGS = /DCARES_STATICLIB
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_DBG) $(STA_LIB_DBG).lib
CARES_LINK   = $(LINK_CMD_LIB)
SPROG_LINK   = $(LINK_CMD_EXE_DBG)
CC_CMD       = $(CC_CMD_DBG)
!ENDIF

!IF "$(CFG)" == "dll-release"
CARES_TARGET = $(DYN_LIB_REL).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY
CARES_LFLAGS = /release $(EX_LIBS_REL) /implib:$(PROG_OUTDIR)\$(IMP_LIB_REL).lib $(PDB_NONE)
SPROG_CFLAGS =
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_REL) $(IMP_LIB_REL).lib
CARES_LINK   = $(LINK_CMD_DLL)
SPROG_LINK   = $(LINK_CMD_EXE_REL)
CC_CMD       = $(CC_CMD_REL)
USE_RES_FILE = TRUE
RC_CMD       = $(RC_CMD_REL)
!ENDIF

!IF "$(CFG)" == "dll-debug"
CARES_TARGET = $(DYN_LIB_DBG).dll
CARES_CFLAGS = /DCARES_BUILDING_LIBRARY /DDEBUGBUILD
CARES_LFLAGS = /debug $(EX_LIBS_DBG) /implib:$(PROG_OUTDIR)\$(IMP_LIB_DBG).lib /pdb:$(PROG_OUTDIR)\$(DYN_LIB_DBG).pdb $(PDBTYPE_CONSOLIDATE)
SPROG_CFLAGS =
SPROG_LFLAGS = /libpath:$(LIB_OUTDIR) $(EX_LIBS_DBG) $(IMP_LIB_DBG).lib
CARES_LINK   = $(LINK_CMD_DLL)
SPROG_LINK   = $(LINK_CMD_EXE_DBG)
CC_CMD       = $(CC_CMD_DBG)
USE_RES_FILE = TRUE
RC_CMD       = $(RC_CMD_DBG)
!ENDIF

# --------------------------------------------
# Makefile.inc provides lists of source files
# --------------------------------------------

!INCLUDE .\Makefile.inc

# ----------------------------
# Build lists of object files
# ----------------------------

!IF [ECHO PROG_OBJS=^$(PROG_OBJDIR)\$(TESTSOURCES: = $(PROG_OBJDIR^)\) > .\prog_objs.inc] == 0
!INCLUDE .\prog_objs.inc
!IF [DEL .\prog_objs.inc]
!ENDIF
!ELSE
!ERROR Problem generating PROG_OBJS list.
!ENDIF
PROG_OBJS = $(PROG_OBJS:.cc=.obj)

!IF [ECHO FUZZ_OBJS=^$(PROG_OBJDIR)\$(FUZZSOURCES: = $(PROG_OBJDIR^)\) > .\fuzz_objs.inc] == 0
!INCLUDE .\fuzz_objs.inc
!IF [DEL .\fuzz_objs.inc]
!ENDIF
!ELSE
!ERROR Problem generating FUZZ_OBJS list.
!ENDIF
FUZZ_OBJS = $(FUZZ_OBJS:.c=.obj)

!IF [ECHO FUZZNAME_OBJS=^$(PROG_OBJDIR)\$(FUZZNAMESOURCES: = $(PROG_OBJDIR^)\) > .\fuzzname_objs.inc] == 0
!INCLUDE .\fuzzname_objs.inc
!IF [DEL .\fuzzname_objs.inc]
!ENDIF
!ELSE
!ERROR Problem generating FUZZNAME_OBJS list.
!ENDIF
FUZZNAME_OBJS = $(FUZZNAME_OBJS:.c=.obj)

!IF [ECHO DNSDUMP_OBJS=^$(PROG_OBJDIR)\$(DUMPSOURCES: = $(PROG_OBJDIR^)\) > .\dnsdump_objs.inc] == 0
!INCLUDE .\dnsdump_objs.inc
!IF [DEL .\dnsdump_objs.inc]
!ENDIF
!ELSE
!ERROR Problem generating DNSDUMP_OBJS list.
!ENDIF
DNSDUMP_OBJS = $(DNSDUMP_OBJS:.cc=.obj)

GMOCK_GTEST_OBJ = $(PROG_OBJDIR)\gmock-gtest-all.obj

# --------------------------------
# Only our custom inference rules
# --------------------------------

.SUFFIXES:
.SUFFIXES: .cc .c

{$(SRCDIR)}.cc{$(PROG_OBJDIR)}.obj:
    $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(SRCDIR)}.c{$(PROG_OBJDIR)}.obj:
    $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /Fo$@ /Fd$(@D)\ /c $<
{$(GMOCK_DIR)}.cc{$(PROG_OBJDIR)}.obj:
    $(CC_CMD) $(CC_CFLAGS) $(SPROG_CFLAGS) /I $(GMOCK_DIR) /Fo$@ /Fd$(@D)\ /c $<


# ---------------------------------------------------------------------
# Main targets
# ---------------------------------------------------------------------

ALL: arestest aresfuzz aresfuzzname dnsdump
    @

test: arestest
    $(PROG_OUTDIR)\arestest
vtest: arestest
    $(PROG_OUTDIR)\arestest -v

arestest: $(TESTSOURCES) $(PROG_OUTDIR) $(PROG_OBJDIR) $(PROG_OBJS) $(GMOCK_GTEST_OBJ)
    $(SPROG_LINK) $(SPROG_LFLAGS) /out:$(PROG_OUTDIR)\arestest.exe $(PROG_OBJS) $(GMOCK_GTEST_OBJ)
    @if exist $(PROG_OUTDIR)\arestest.exe.manifest mt -nologo -manifest $(PROG_OUTDIR)\arestest.exe.manifest -outputresource:$(PROG_OUTDIR)\arestest.exe;1

aresfuzz: $(FUZZSOURCES) $(PROG_OUTDIR) $(PROG_OBJDIR) $(FUZZ_OBJS)
    $(SPROG_LINK) $(SPROG_LFLAGS) /out:$(PROG_OUTDIR)\aresfuzz.exe $(FUZZ_OBJS)
    @if exist $(PROG_OUTDIR)\aresfuzz.exe.manifest mt -nologo -manifest $(PROG_OUTDIR)\aresfuzz.exe.manifest -outputresource:$(PROG_OUTDIR)\aresfuzz.exe;1

aresfuzzname: $(FUZZNAMESOURCES) $(PROG_OUTDIR) $(PROG_OBJDIR) $(FUZZNAME_OBJS)
    $(SPROG_LINK) $(SPROG_LFLAGS) /out:$(PROG_OUTDIR)\aresfuzzname.exe $(FUZZNAME_OBJS)
    @if exist $(PROG_OUTDIR)\aresfuzzname.exe.manifest mt -nologo -manifest $(PROG_OUTDIR)\aresfuzzname.exe.manifest -outputresource:$(PROG_OUTDIR)\aresfuzzname.exe;1

dnsdump: $(DUMPSOURCES) $(PROG_OUTDIR) $(PROG_OBJDIR) $(DNSDUMP_OBJS)
    $(SPROG_LINK) $(SPROG_LFLAGS) /out:$(PROG_OUTDIR)\dnsdump.exe $(DNSDUMP_OBJS)
    @if exist $(PROG_OUTDIR)\dnsdump.exe.manifest mt -nologo -manifest $(PROG_OUTDIR)\dnsdump.exe.manifest -outputresource:$(PROG_OUTDIR)\dnsdump.exe;1

$(PROG_OUTDIR): $(PROG_DIR)
    @if not exist $(PROG_OUTDIR) mkdir $(PROG_OUTDIR)

$(PROG_OBJDIR): $(PROG_OUTDIR)
    @if not exist $(PROG_OBJDIR) mkdir $(PROG_OBJDIR)

clean:
    @-RMDIR /S /Q $(PROG_OUTDIR) >NUL 2>&1

$(BASE_DIR):
    @if not exist $(BASE_DIR) mkdir $(BASE_DIR)

$(PROG_DIR): $(BASE_DIR)
    @if not exist $(PROG_DIR) mkdir $(PROG_DIR)

# End of Makefile.msvc
