diff --git a/ports/windows/Makefile b/ports/windows/Makefile
index cb2ebc22f7..b1d2d35c9a 100644
--- a/ports/windows/Makefile
+++ b/ports/windows/Makefile
@@ -1,11 +1,27 @@
+# Select the variant to build for.
+VARIANT ?= standard
+
+# If the build directory is not given, make it reflect the variant name.
+BUILD ?= build-$(VARIANT)
+
+VARIANT_DIR ?= variants/$(VARIANT)
+ifeq ($(wildcard $(VARIANT_DIR)/.),)
+$(error Invalid VARIANT specified: $(VARIANT_DIR))
+endif
+
include ../../py/mkenv.mk
-include mpconfigport.mk
+include $(VARIANT_DIR)/mpconfigvariant.mk
-# define main target
-PROG = micropython
+FROZEN_MANIFEST ?= variants/manifest.py
+
+# Define main target
+# This should be configured by the mpconfigvariant.mk
+PROG ?= micropython
# qstr definitions (must come before including py.mk)
QSTR_DEFS = ../unix/qstrdefsport.h
+QSTR_GLOBAL_DEPENDENCIES = $(VARIANT_DIR)/mpconfigvariant.h
# include py core make definitions
include $(TOP)/py/py.mk
@@ -13,6 +29,7 @@ include $(TOP)/py/py.mk
INC += -I.
INC += -I$(TOP)
INC += -I$(BUILD)
+INC += -I$(VARIANT_DIR)
# compiler settings
CFLAGS = $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
@@ -41,7 +58,8 @@ SRC_C = \
init.c \
sleep.c \
fmode.c \
- $(SRC_MOD)
+ $(SRC_MOD) \
+ $(wildcard $(VARIANT_DIR)/*.c)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
diff --git a/ports/windows/README.md b/ports/windows/README.md
index 55e23de7bf..713ea82b87 100644
--- a/ports/windows/README.md
+++ b/ports/windows/README.md
@@ -71,6 +71,26 @@ To build from the command line:
msbuild ../../mpy-cross/mpy-cross.vcxproj
msbuild micropython.vcxproj
+__Variants__
+
+The msvc port supports variants (like the unix and windows mingw ports) and the one which gets built is
+controlled by the `PyVariant` msbuild property. It defaults to `standard`.
+The other variants can be built like:
+
+ msbuild micropython.vcxproj /p:PyVariant=dev
+
+Or by adding a file [Directory.build.props](https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build#directorybuildprops-and-directorybuildtargets) in this directory or a parent directory:
+
+```xml
+
+
+ dev
+
+
+```
+
+See [paths.props](msvc/paths.props) for other related variables like build and variant directories.
+
__Stack usage__
The msvc compiler is quite stack-hungry which might result in a "maximum recursion depth exceeded"
diff --git a/ports/windows/micropython.vcxproj b/ports/windows/micropython.vcxproj
index 1beca9e508..6817d6ed13 100644
--- a/ports/windows/micropython.vcxproj
+++ b/ports/windows/micropython.vcxproj
@@ -64,6 +64,7 @@
msvc/user.props
+ $(PyProg)
@@ -95,6 +96,7 @@
+
diff --git a/ports/windows/mpconfigport.h b/ports/windows/mpconfigport.h
index f22af9b7fc..96405bc5d2 100644
--- a/ports/windows/mpconfigport.h
+++ b/ports/windows/mpconfigport.h
@@ -26,6 +26,9 @@
// options to control how MicroPython is built
+// Variant-specific definitions.
+#include "mpconfigvariant.h"
+
// By default use MicroPython version of readline
#ifndef MICROPY_USE_READLINE
#define MICROPY_USE_READLINE (1)
@@ -54,9 +57,13 @@
#define MICROPY_REPL_AUTO_INDENT (1)
#define MICROPY_HELPER_LEXER_UNIX (1)
#define MICROPY_ENABLE_SOURCE_LINE (1)
+#ifndef MICROPY_FLOAT_IMPL
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE)
+#endif
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
+#ifndef MICROPY_STREAMS_NON_BLOCK
#define MICROPY_STREAMS_NON_BLOCK (1)
+#endif
#define MICROPY_STREAMS_POSIX_API (1)
#define MICROPY_OPT_COMPUTED_GOTO (0)
#define MICROPY_MODULE_WEAK_LINKS (1)
@@ -77,8 +84,12 @@
#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1)
#define MICROPY_PY_BUILTINS_INPUT (1)
#define MICROPY_PY_BUILTINS_POW3 (1)
+#ifndef MICROPY_PY_BUILTINS_HELP
#define MICROPY_PY_BUILTINS_HELP (1)
+#endif
+#ifndef MICROPY_PY_BUILTINS_HELP_MODULES
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
+#endif
#define MICROPY_PY_BUILTINS_ROUND_INT (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
@@ -97,16 +108,18 @@
#define MICROPY_PY_SYS_EXC_INFO (1)
#define MICROPY_PY_COLLECTIONS_DEQUE (1)
#define MICROPY_PY_COLLECTIONS_ORDEREDDICT (1)
+#ifndef MICROPY_PY_MATH_SPECIAL_FUNCTIONS
#define MICROPY_PY_MATH_SPECIAL_FUNCTIONS (1)
-#define MICROPY_PY_MATH_ISCLOSE (1)
+#endif
+#define MICROPY_PY_MATH_ISCLOSE (MICROPY_PY_MATH_SPECIAL_FUNCTIONS)
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_IO_IOBASE (1)
#define MICROPY_PY_IO_FILEIO (1)
#define MICROPY_PY_GC_COLLECT_RETVAL (1)
-#define MICROPY_MODULE_FROZEN_STR (0)
-
+#ifndef MICROPY_STACKLESS
#define MICROPY_STACKLESS (0)
#define MICROPY_STACKLESS_STRICT (0)
+#endif
#define MICROPY_PY_UTIME (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
diff --git a/ports/windows/mpconfigport.mk b/ports/windows/mpconfigport.mk
index a2c618f143..3b7cf2100d 100644
--- a/ports/windows/mpconfigport.mk
+++ b/ports/windows/mpconfigport.mk
@@ -1,12 +1,9 @@
# Enable/disable modules and 3rd-party libs to be included in interpreter
# Build 32-bit binaries on a 64-bit host
-MICROPY_FORCE_32BIT = 0
+MICROPY_FORCE_32BIT ?= 0
# This variable can take the following values:
# 0 - no readline, just simple stdin input
# 1 - use MicroPython version of readline
-MICROPY_USE_READLINE = 1
-
-# ffi module requires libffi (libffi-dev Debian package)
-MICROPY_PY_FFI = 0
+MICROPY_USE_READLINE ?= 1
diff --git a/ports/windows/msvc/common.props b/ports/windows/msvc/common.props
index fcad5aeb6b..ab9b055def 100644
--- a/ports/windows/msvc/common.props
+++ b/ports/windows/msvc/common.props
@@ -1,7 +1,15 @@
+
+
+ standard
+ build-$(PyVariant)
+
+
@@ -31,6 +39,7 @@
$(PyTargetDir)%(FileName)%(Extension)
+
@@ -25,11 +27,12 @@
$([System.IO.Path]::GetFullPath(`$(MSBuildThisFileDirectory)..\..\..`))\
$(PyBaseDir)ports\windows\
- $(PyWinDir)build\
+ $(PyWinDir)$(PyBuild)\
+ $(PyWinDir)variants\$(PyVariant)\
$(PyWinDir)
- $(PyIncDirs);$(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc
+ $(PyIncDirs);$(PyBaseDir);$(PyWinDir);$(PyBuildDir);$(PyWinDir)msvc;$(PyVariantDir)