diff --git a/python/tvm/contrib/cc.py b/python/tvm/contrib/cc.py
index d9379bbd7efd9278f008f12af2123bdfdc0a84e1..229b58ae19e52a71ac24ce63c8de3a0e0879d437 100644
--- a/python/tvm/contrib/cc.py
+++ b/python/tvm/contrib/cc.py
@@ -4,6 +4,10 @@ from __future__ import absolute_import as _abs
 import sys
 import subprocess
 
+import os
+from .util import tempdir
+
+
 def create_shared(output,
                   objects,
                   options=None,
@@ -24,26 +28,85 @@ def create_shared(output,
     cc : str, optional
         The compile string.
     """
+    if sys.platform == "darwin" or sys.platform.startswith('linux'):
+        _linux_shared(output, objects, options, cc)
+    elif sys.platform == "win32":
+        _windows_shared(output, objects, options)
+    else:
+        raise ValueError("Unsupported platform")
+
+
+def _linux_shared(output, objects, options, cc="g++"):
     cmd = [cc]
     cmd += ["-shared", "-fPIC"]
-
     if sys.platform == "darwin":
         cmd += ["-undefined", "dynamic_lookup"]
     cmd += ["-o", output]
-
     if isinstance(objects, str):
         cmd += [objects]
     else:
         cmd += objects
-
     if options:
         cmd += options
-
     proc = subprocess.Popen(
         cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
     (out, _) = proc.communicate()
+    if proc.returncode != 0:
+        msg = "Compilation error:\n"
+        msg += str(out)
+        raise RuntimeError(msg)
+
+
+def _windows_shared(output, objects, options):
+    cl_cmd = ["cl"]
+    cl_cmd += ["-c"]
+    if isinstance(objects, str):
+        objects = [objects]
+    cl_cmd += objects
+    if options:
+        cl_cmd += options
+
+    temp = tempdir()
+    dllmain_path = temp.relpath("dllmain.cc")
+    with open(dllmain_path, "w") as dllmain_obj:
+        dllmain_obj.write('#include <windows.h>\
+BOOL APIENTRY DllMain( HMODULE hModule,\
+                       DWORD  ul_reason_for_call,\
+                       LPVOID lpReserved)\
+{return TRUE;}')
+
+    cl_cmd += [dllmain_path]
+
+    temp_path = dllmain_path.replace("dllmain.cc", "")
+    cl_cmd += ["-Fo:" + temp_path]
+
+    proc = subprocess.Popen(
+        cl_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    (out, _) = proc.communicate()
+    if proc.returncode != 0:
+        msg = "Compilation error:\n"
+        msg += str(out)
+        raise RuntimeError(msg)
+    link_cmd = ["link"]
+    link_cmd += ["-dll", "-FORCE:MULTIPLE"]
+
+    for obj in objects:
+        if obj.endswith(".cc"):
+            (_, temp_file_name) = os.path.split(obj)
+            (shot_name, _) = os.path.splitext(temp_file_name)
+            link_cmd += [os.path.join(temp_path, shot_name + ".obj")]
+        if obj.endswith(".o"):
+            link_cmd += [obj]
+
+    link_cmd += ["-EXPORT:__tvm_main__"]
+    link_cmd += [temp_path + "dllmain.obj"]
+    link_cmd += ["-out:" + output]
 
+    proc = subprocess.Popen(
+        link_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+    (out, _) = proc.communicate()
     if proc.returncode != 0:
         msg = "Compilation error:\n"
-        msg += out
+        msg += str(out)
+
         raise RuntimeError(msg)
diff --git a/python/tvm/contrib/util.py b/python/tvm/contrib/util.py
index 9b393ab37b15ad6f5fa81cd2d086cd5892aa30b6..93d5b897c7c1e82f20ae463cde7e0af006430143 100644
--- a/python/tvm/contrib/util.py
+++ b/python/tvm/contrib/util.py
@@ -16,7 +16,7 @@ class TempDirectory(object):
     def remove(self):
         """Remote the tmp dir"""
         if self.temp_dir:
-            self._rmtree(self.temp_dir)
+            self._rmtree(self.temp_dir, ignore_errors=True)
             self.temp_dir = None
 
     def __del__(self):
diff --git a/python/tvm/module.py b/python/tvm/module.py
index 9c44a9f1e34b8e280e84d2676f89249a693857a1..055ae73089872d94a43e868e73ef7968d21031ee 100644
--- a/python/tvm/module.py
+++ b/python/tvm/module.py
@@ -2,14 +2,17 @@
 from __future__ import absolute_import as _abs
 
 from collections import namedtuple
+
 from ._ffi.function import ModuleBase, _set_class_module
 from ._ffi.function import _init_api
 from .contrib import cc as _cc, tar as _tar, util as _util
 
 ProfileResult = namedtuple("ProfileResult", ["mean"])
 
+
 class Module(ModuleBase):
     """Module container of all TVM generated functions"""
+
     def __repr__(self):
         return "Module(%s, %x)" % (self.type_key, self.handle.value)
 
@@ -135,11 +138,13 @@ class Module(ModuleBase):
         try:
             feval = _RPCTimeEvaluator(
                 self, func_name, ctx.device_type, ctx.device_id, number)
+
             def evaluator(*args):
                 """Internal wrapped evaluator."""
                 # Wrap feval so we can add more stats in future.
                 mean = feval(*args)
                 return ProfileResult(mean=mean)
+
             return evaluator
         except NameError:
             raise NameError("time_evaluate is only supported when RPC is enabled")
diff --git a/src/codegen/llvm/codegen_cpu.cc b/src/codegen/llvm/codegen_cpu.cc
index b23fdf18f07c95fa58e9590c01f5fa7b7b607bbf..7b3d1301f756c2026fe07d5e34afa4181cee9f43 100644
--- a/src/codegen/llvm/codegen_cpu.cc
+++ b/src/codegen/llvm/codegen_cpu.cc
@@ -226,6 +226,7 @@ llvm::GlobalVariable* CodeGenCPU::InitContextPtr(
       name);
   gv->setAlignment(data_layout_->getTypeAllocSize(p_type));
   gv->setInitializer(llvm::Constant::getNullValue(p_type));
+  gv->setDLLStorageClass(llvm::GlobalValue::DLLStorageClassTypes::DLLExportStorageClass);
   return gv;
 }
 
diff --git a/src/codegen/llvm/codegen_llvm.cc b/src/codegen/llvm/codegen_llvm.cc
index f0c022316083f03b9944f61f5ecb47e546584a12..97a5bb84e06e7f1a9ba3223809b3320b0c375486 100644
--- a/src/codegen/llvm/codegen_llvm.cc
+++ b/src/codegen/llvm/codegen_llvm.cc
@@ -117,6 +117,7 @@ void CodeGenLLVM::AddFunctionInternal(const LoweredFunc& f, bool ret_void) {
       ftype, llvm::Function::ExternalLinkage,
       f->name, module_.get());
   function_->setCallingConv(llvm::CallingConv::C);
+  function_->setDLLStorageClass(llvm::GlobalValue::DLLStorageClassTypes::DLLExportStorageClass);
   // set var map and align information
   auto arg_it = function_->arg_begin();
   for (size_t i = 0; i < f->args.size(); ++i, ++arg_it) {
diff --git a/src/codegen/llvm/llvm_common.h b/src/codegen/llvm/llvm_common.h
index fa033dd704366c0e24a1f5b8b63654eaafc16a83..da905f4709e04557320d380919f29c2c0b7d528b 100644
--- a/src/codegen/llvm/llvm_common.h
+++ b/src/codegen/llvm/llvm_common.h
@@ -41,6 +41,7 @@
 #include <llvm/Target/TargetMachine.h>
 #include <llvm/Target/TargetOptions.h>
 #include <llvm/IRReader/IRReader.h>
+#include <llvm/CodeGen/TargetLoweringObjectFileImpl.h>
 
 #include <utility>
 #include <string>
diff --git a/tests/python/unittest/test_module_load.py b/tests/python/unittest/test_module_load.py
index 43858dcf08d7b53b9751cfcbb44780be404e6976..210ef954464c24c98e3ae7a9113a4adb65f9b90f 100644
--- a/tests/python/unittest/test_module_load.py
+++ b/tests/python/unittest/test_module_load.py
@@ -2,6 +2,7 @@ import tvm
 from tvm.contrib import cc, util
 import ctypes
 import os
+import sys
 import numpy as np
 import subprocess
 
@@ -88,7 +89,13 @@ def test_device_module_dump():
             return
         temp = util.tempdir()
         name = "myadd_%s" % device
-        f = tvm.build(s, [A, B], device, "llvm -system-lib", name=name)
+        if sys.platform == "darwin" or sys.platform.startswith('linux'):
+            f = tvm.build(s, [A, B], device, "llvm -system-lib", name=name)
+        elif sys.platform == "win32":
+            f = tvm.build(s, [A, B], device, "llvm", name=name)
+        else:
+            raise ValueError("Unsupported platform")
+       
         path_dso = temp.relpath("dev_lib.so")
         f.export_library(path_dso)
 
@@ -96,10 +103,11 @@ def test_device_module_dump():
         a = tvm.nd.array(np.random.uniform(size=1024).astype(A.dtype), ctx)
         b = tvm.nd.array(np.zeros(1024, dtype=A.dtype), ctx)
         f1(a, b)
-        f2 = tvm.module.system_lib()
-        np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
-        f2[name](a, b)
         np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
+        if sys.platform != "win32":
+            f2 = tvm.module.system_lib()
+            f2[name](a, b)
+            np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
 
     check_device("cuda")
     check_device("opencl")
@@ -164,8 +172,9 @@ def test_combine_module_llvm():
         np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
         mm['myadd2'](a, b)
         np.testing.assert_equal(b.asnumpy(), a.asnumpy() + 1)
-
-    check_system_lib()
+    
+    if sys.platform != "win32":
+        check_system_lib()
     check_llvm()