# Microsoft Visual C++

# (C) Copyright David Abrahams 2001. Permission to copy, use,
# modify, sell and distribute this software is granted provided this
# copyright notice appears in all copies. This software is provided
# "as is" without express or implied warranty, and with no claim as
# to its suitability for any purpose.

# compute MSVC tool path
# You can either put the msvc bin directory in your PATH, or you can set
# MSVCDir to point at the msvc installation directory
MSVC_TOOL_PATH ?= "$(MSVCDir)"$(SLASH)bin$(SLASH) ;
MSVC_TOOL_PATH ?= "$(VISUALC)"$(SLASH)bin$(SLASH) ;
MSVC_TOOL_PATH ?= "" ; # Don't clobber adjoining text if MSVCDir isn't set

flags msvc CFLAGS <debug-symbols>on : /Zi ;
flags msvc LINKFLAGS <debug-symbols>on : /DEBUG ;

flags msvc CFLAGS <optimization>off : /Od ;
flags msvc CFLAGS <optimization>speed : /O2 ;
flags msvc CFLAGS <optimization>space : /O1 ;
flags msvc CFLAGS <inlining>off : /Ob0 ;
flags msvc CFLAGS <inlining>on : /Ob1 ;
flags msvc CFLAGS <inline>full : /Ob2 ;
flags msvc CFLAGS <exception-handling>on : /GX ;
flags msvc CFLAGS <rtti>on : /GR ;

# Note that these two options actually imply multithreading support on MSVC
# because there is no single-threaded dynamic runtime library. Specifying
# <threading>multi would be a bad idea, though, because no option would be
# matched when the build uses the default settings of <runtime-link>dynamic
# and <threading>single.
flags msvc CFLAGS <runtime-build>release/<runtime-link>dynamic : /MD ;
flags msvc CFLAGS <runtime-build>debug/<runtime-link>dynamic : /MDd ;

flags msvc CFLAGS <runtime-build>release/<runtime-link>static/<threading>single : /ML ;
flags msvc CFLAGS <runtime-build>debug/<runtime-link>static/<threading>single : /MLd ;
flags msvc CFLAGS <runtime-build>release/<runtime-link>static/<threading>multi : /MT ;
flags msvc CFLAGS <runtime-build>debug/<runtime-link>static/<threading>multi : /MTd ;

flags msvc CFLAGS <cflags> ;
flags msvc C++FLAGS <cxxflags> ;
flags msvc DEFINES <define> ;
flags msvc UNDEFS <undef> ;
flags msvc HDRS <include> ;

flags msvc STDHDRS : $(MSVCDir)$(SLASH)include ;
flags msvc STDLIBPATH : $(MSVCDir)$(SLASH)lib ;
flags msvc LIBPATH <library-path> ;
flags msvc NEEDLIBS <library-file> ;
flags msvc FINDLIBS <find-library> ;
flags msvc LINKFLAGS <target-type>DLL : /DLL ;

#### Link ####

rule Link-action
{
    with-command-file msvc-Link-action $(<) : $(>) $(NEEDLIBS) ;
    if $(<[2])
    {
        # incremental linking a DLL causes no end of problems: if the
        # actual exports don't change, the import .lib file is never
        # updated. Therefore, the .lib is always out-of-date and gets
        # rebuilt every time. I'm not sure that incremental linking is
        # such a great idea in general, but in this case I'm sure we
        # don't want it.
        NOINCREMENTAL on $(<) = /INCREMENTAL:NO ;
    }
}

actions together msvc-Link-action bind NEEDLIBS
{
    $(MSVC_TOOL_PATH)link /nologo $(NOINCREMENTAL) $(LINKFLAGS) /PDB:"$(<[1]:S=.pdb)" /out:"$(<[1])" /LIBPATH:$(LIBPATH) /LIBPATH:$(STDLIBPATH) "$(FINDLIBS)" @"$(>)"
}

#### Cc #####

rule Cc-action
{
    msvc-Cc-action $(<) : $(>) ;
}

actions msvc-Cc-action
{
    $(MSVC_TOOL_PATH)cl /Zm400 -nologo -c -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -Fo"$(<)" "$(>)"
}

#### C++ ####
rule C++-action
{
    msvc-C++-action $(<) : $(>) ;
}

actions msvc-C++-action
{
    $(MSVC_TOOL_PATH)cl /Zm400 -nologo -GX -c -U$(UNDEFS) -D$(DEFINES) $(CFLAGS) $(C++FLAGS) -I"$(HDRS)" -I"$(STDHDRS)" -Fo"$(<)" -Tp"$(>)"
}

#### Archive ####
rule Archive-action
{
    msvc-Archive-action $(<) : $(>) ;
}

actions updated together piecemeal msvc-Archive-action
{
	if exist "$(<)" set _$(<:B)_="$(<)"
	$(MSVC_TOOL_PATH)link /lib /out:"$(<)" %_$(<:B)_% "$(>)"
}

