diff --git a/config/BUILD.gn b/config/BUILD.gn
index ed94a16a0..3e4a62d24 100644
--- a/config/BUILD.gn
+++ b/config/BUILD.gn
@@ -122,13 +122,13 @@ config("debug") {
     defines += [ "DYNAMIC_ANNOTATIONS_PREFIX=NACL_" ]
   }

-  if (is_win) {
+  if (is_win && !is_mingw) {
     if (!enable_iterator_debugging && !use_custom_libcxx) {
       # Iterator debugging is enabled by default by the compiler on debug
       # builds, and we have to tell it to turn it off.
       defines += [ "_HAS_ITERATOR_DEBUGGING=0" ]
     }
-  } else if ((is_linux || is_chromeos) && current_cpu == "x64" &&
+  } else if ((is_linux || is_chromeos || is_mingw) && current_cpu == "x64" &&
              enable_iterator_debugging) {
     # Enable libstdc++ debugging facilities to help catch problems early, see
     # http://crbug.com/65151 .
@@ -163,7 +163,7 @@ config("release") {

 # This config defines the default libraries applied to all targets.
 config("default_libs") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     # TODO(brettw) this list of defaults should probably be smaller, and
     # instead the targets that use the less common ones (e.g. wininet or
     # winspool) should include those explicitly.
@@ -289,8 +289,13 @@ group("shared_library_deps") {

 # Windows linker setup for EXEs and DLLs.
 if (is_win) {
-  _windows_linker_configs = [
-    "//build/config/win:sdk_link",
+  _windows_linker_configs = []
+  if(!is_mingw){
+    _windows_linker_configs += [
+      "//build/config/win:sdk_link",
+    ]
+  }
+  _windows_linker_configs += [
     "//build/config/win:common_linker_setup",
   ]
 }
diff --git a/config/BUILDCONFIG.gn b/config/BUILDCONFIG.gn
index 0ef73ab2b..527203c6d 100644
--- a/config/BUILDCONFIG.gn
+++ b/config/BUILDCONFIG.gn
@@ -130,8 +130,12 @@ declare_args() {
   # separate flags.
   is_official_build = false

+  # Set to true when compiling with the MinGW GCC compiler on the MSYS2 environment.
+  is_mingw = getenv("MSYSTEM") != "" && getenv("MSYSTEM") != "MSYS"
+
   # Set to true when compiling with the Clang compiler.
   is_clang = current_os != "linux" ||
+            !(getenv("MSYSTEM") != "" && getenv("MSYSTEM") != "MSYS") ||
              (current_cpu != "s390x" && current_cpu != "s390" &&
               current_cpu != "ppc64" && current_cpu != "ppc" &&
               current_cpu != "mips" && current_cpu != "mips64" &&
@@ -201,11 +205,15 @@ if (host_toolchain == "") {
     if (target_cpu == "x86" || target_cpu == "x64") {
       if (is_clang) {
         host_toolchain = "//build/toolchain/win:win_clang_$target_cpu"
+      } else if (is_mingw) {
+        host_toolchain = "//build/toolchain/win:mingw_$target_cpu"
       } else {
         host_toolchain = "//build/toolchain/win:$target_cpu"
       }
     } else if (is_clang) {
       host_toolchain = "//build/toolchain/win:win_clang_$host_cpu"
+    } else if (is_mingw) {
+      host_toolchain = "//build/toolchain/win:mingw_$host_cpu"
     } else {
       host_toolchain = "//build/toolchain/win:$host_cpu"
     }
@@ -242,6 +250,8 @@ if (target_os == "android") {
   # Beware, win cross builds have some caveats, see docs/win_cross.md
   if (is_clang) {
     _default_toolchain = "//build/toolchain/win:win_clang_$target_cpu"
+  } else if (is_mingw) {
+    _default_toolchain = "//build/toolchain/win:mingw_$target_cpu"
   } else {
     _default_toolchain = "//build/toolchain/win:$target_cpu"
   }
diff --git a/config/compiler/BUILD.gn b/config/compiler/BUILD.gn
index 0c8743726..c60704e6d 100644
--- a/config/compiler/BUILD.gn
+++ b/config/compiler/BUILD.gn
@@ -299,8 +299,8 @@ config("compiler") {
   }

   # In general, Windows is totally different, but all the other builds share
-  # some common compiler and linker configuration.
-  if (!is_win) {
+  # some common GCC configuration.
+  if (!is_win || is_mingw) {
     # Common POSIX compiler flags setup.
     # --------------------------------
     cflags += [ "-fno-strict-aliasing" ]  # See http://crbug.com/32204
@@ -314,7 +314,7 @@ config("compiler") {
       } else {
         cflags += [ "-fstack-protector" ]
       }
-    } else if ((is_posix && !is_chromeos_ash && !is_nacl) || is_fuchsia) {
+    } else if ((is_posix && !is_chromeos && !is_nacl) || is_fuchsia || is_mingw) {
       # TODO(phajdan.jr): Use -fstack-protector-strong when our gcc supports it.
       # See also https://crbug.com/533294
       cflags += [ "--param=ssp-buffer-size=4" ]
@@ -325,6 +325,12 @@ config("compiler") {
       } else if (current_os != "aix") {
         # Not available on aix.
         cflags += [ "-fstack-protector" ]
+        if(is_mingw) {
+          # In MingW's GCC -fstack-protector
+          # needs to be passed to the linker as well
+          # for it to link against the ssp library
+          ldflags += [ "-fstack-protector" ]
+        }
       }
     }

@@ -354,7 +360,7 @@ config("compiler") {

   # Non-Mac Posix and Fuchsia compiler flags setup.
   # -----------------------------------
-  if ((is_posix && !is_apple) || is_fuchsia) {
+  if ((is_posix && !is_apple) || is_fuchsia || is_mingw) {
     if (enable_profiling) {
       if (!is_debug) {
         cflags += [ "-g" ]
@@ -503,7 +509,7 @@ config("compiler") {
     # TODO(thakis): Make the driver pass --color-diagnostics to the linker
     # if -fcolor-diagnostics is passed to it, and pass -fcolor-diagnostics
     # in ldflags instead.
-    if (is_win) {
+    if (is_win && !is_mingw) {
       # On Windows, we call the linker directly, instead of calling it through
       # the driver.
       ldflags += [ "--color-diagnostics" ]
@@ -538,7 +544,7 @@ config("compiler") {

   # C11/C++11 compiler flags setup.
   # ---------------------------
-  if (is_linux || is_chromeos || is_android || (is_nacl && is_clang) ||
+  if (is_linux || is_mingw || is_chromeos || is_android || (is_nacl && is_clang) ||
       current_os == "aix") {
     if (target_os == "android") {
       cxx11_override = use_cxx11_on_android
@@ -642,7 +648,7 @@ config("compiler") {
     # should be able to better manage binary size increases on its own.
     import_instr_limit = 5

-    if (is_win) {
+    if (is_win && !is_mingw) {
       ldflags += [
         "/opt:lldltojobs=all",
         "-mllvm:-import-instr-limit=$import_instr_limit",
@@ -689,7 +695,7 @@ config("compiler") {
     # Tracked by llvm bug: https://bugs.llvm.org/show_bug.cgi?id=48245
     if (!is_android || current_cpu == "arm64") {
       cflags += [ "-fwhole-program-vtables" ]
-      if (!is_win) {
+      if (!is_win || is_mingw) {
         ldflags += [ "-fwhole-program-vtables" ]
       }
     }
@@ -707,7 +713,7 @@ config("compiler") {
   if (compiler_timing) {
     if (is_clang && !is_nacl) {
       cflags += [ "-ftime-trace" ]
-    } else if (is_win) {
+    } else if (is_win && !is_mingw) {
       cflags += [
         # "Documented" here:
         # http://aras-p.info/blog/2017/10/23/Best-unknown-MSVC-flag-d2cgsummary/
@@ -758,7 +764,7 @@ config("compiler") {
   # Assign any flags set for the C compiler to asmflags so that they are sent
   # to the assembler. The Windows assembler takes different types of flags
   # so only do so for posix platforms.
-  if (is_posix || is_fuchsia) {
+  if (is_posix || is_fuchsia || is_mingw) {
     asmflags += cflags
     asmflags += cflags_c
   }
@@ -812,7 +818,7 @@ config("compiler_cpu_abi") {
   ldflags = []
   defines = []

-  if ((is_posix && !is_apple) || is_fuchsia) {
+  if ((is_posix && !is_apple) || is_fuchsia || is_mingw) {
     # CPU architecture. We may or may not be doing a cross compile now, so for
     # simplicity we always explicitly set the architecture.
     if (current_cpu == "x64") {
@@ -1166,7 +1172,7 @@ config("compiler_deterministic") {
   # Eliminate build metadata (__DATE__, __TIME__ and __TIMESTAMP__) for
   # deterministic build.  See https://crbug.com/314403
   if (!is_official_build) {
-    if (is_win && !is_clang) {
+    if (is_win && !is_clang && !is_mingw) {
       cflags += [
         "/wd4117",  # Trying to define or undefine a predefined macro.
         "/D__DATE__=",
@@ -1327,7 +1333,7 @@ config("default_warnings") {
   cflags_cc = []
   ldflags = []

-  if (is_win) {
+  if (is_win && !is_mingw) {
     if (treat_warnings_as_errors) {
       cflags += [ "/WX" ]
     }
@@ -1537,15 +1543,32 @@ config("default_warnings") {
       # files.
       cflags += [ "-Wno-packed-not-aligned" ]
     }
+
+    if (is_mingw) {
+      cflags += [
+        "-Wno-attributes",           # "__decspec(dllimport) inline"
+        "-Wno-format",               # PRIu64 llu support on MinGW
+        "-Wno-unused-but-set-variable",
+        "-Wno-stringop-overflow",    # False positive overflow error on gcc 10
+
+      ]
+      cflags_cc += [
+        "-Wno-subobject-linkage",    # Tests having code in header files
+      ]
+    }
   }

   # Common Clang and GCC warning setup.
-  if (!is_win || is_clang) {
+  if (!is_win || is_clang || is_mingw) {
     cflags += [
       # Disables.
       "-Wno-missing-field-initializers",  # "struct foo f = {0};"
       "-Wno-unused-parameter",  # Unused function parameters.
+      "-Wno-invalid-offsetof", # Use of "conditionally-supported" offsetof in c++17
     ]
+    if(is_clang){
+      cflags += ["-Wno-range-loop-construct"] # Use of "conditionally-supported" offsetof in c++17
+    }
   }

   if (is_clang) {
@@ -1630,7 +1653,7 @@ config("default_warnings") {
 # part of Chromium.

 config("chromium_code") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     cflags = [ "/W4" ]  # Warning level 4.

     if (is_clang) {
@@ -1723,7 +1746,7 @@ config("no_chromium_code") {
   cflags_cc = []
   defines = []

-  if (is_win) {
+  if (is_win && !is_mingw) {
     cflags += [
       "/W3",  # Warning level 3.
       "/wd4800",  # Disable warning when forcing value to bool.
@@ -1782,7 +1805,7 @@ config("noshadowing") {
 # Allows turning Run-Time Type Identification on or off.

 config("rtti") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     cflags_cc = [ "/GR" ]
   } else {
     cflags_cc = [ "-frtti" ]
@@ -1792,7 +1815,7 @@ config("rtti") {
 config("no_rtti") {
   # Some sanitizer configs may require RTTI to be left enabled globally
   if (!use_rtti) {
-    if (is_win) {
+    if (is_win && !is_mingw) {
       cflags_cc = [ "/GR-" ]
     } else {
       cflags_cc = [ "-fno-rtti" ]
@@ -1845,7 +1868,7 @@ config("thin_archive") {
 # Note: exceptions are disallowed in Google code.

 config("exceptions") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     # Enables exceptions in the STL.
     if (!use_custom_libcxx) {
       defines = [ "_HAS_EXCEPTIONS=1" ]
@@ -1854,11 +1877,17 @@ config("exceptions") {
   } else {
     cflags_cc = [ "-fexceptions" ]
     cflags_objcc = cflags_cc
+    if (is_mingw && exclude_unwind_tables) {
+      # With exceptions explicitly allowed,
+      # override exclude_unwind_tables or
+      # linking will fail on MinGW
+      cflags_cc += [ "-funwind-tables", "-fasynchronous-unwind-tables" ]
+    }
   }
 }

 config("no_exceptions") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     # Disables exceptions in the STL.
     # libc++ uses the __has_feature macro to control whether to use exceptions,
     # so defining this macro is unnecessary. Defining _HAS_EXCEPTIONS to 0 also
@@ -1928,7 +1957,7 @@ config("no_shorten_64_warnings") {
     if (is_clang) {
       cflags = [ "-Wno-shorten-64-to-32" ]
     } else {
-      if (is_win) {
+      if (is_win && !is_mingw) {
         # MSVC does not have an explicit warning equivalent to
         # -Wshorten-64-to-32 but 4267 warns for size_t -> int
         # on 64-bit builds, so is the closest.
@@ -1968,12 +1997,22 @@ config("no_incompatible_pointer_warnings") {

 # Shared settings for both "optimize" and "optimize_max" configs.
 # IMPORTANT: On Windows "/O1" and "/O2" must go before the common flags.
-if (is_win) {
-  common_optimize_on_cflags = [
+if (is_win && !is_mingw) {
+  common_optimize_on_cflags = []
+  if(is_clang) {
+    common_optimize_on_cflags += [
     "/Ob2",  # Both explicit and auto inlining.
+    ]
+  } else {
+  common_optimize_on_cflags += [
+    "/Ob3",  # Both explicit and auto inlining.
+    ]
+  }
+  common_optimize_on_cflags += [
     "/Oy-",  # Disable omitting frame pointers, must be after /O2.
     "/Zc:inline",  # Remove unreferenced COMDAT (faster links).
   ]
+
   if (!is_asan) {
     common_optimize_on_cflags += [
       # Put data in separate COMDATs. This allows the linker
@@ -2069,7 +2108,7 @@ config("default_stack_frames") {

 # Default "optimization on" config.
 config("optimize") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     if (chrome_pgo_phase != 2) {
       # Favor size over speed, /O1 must be before the common flags.
       # /O1 implies /Os and /GF.
@@ -2104,7 +2143,7 @@ config("optimize") {

 # Turn off optimizations.
 config("no_optimize") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     cflags = [
       "/Od",  # Disable optimization.
       "/Ob0",  # Disable all inlining (on by default).
@@ -2156,7 +2195,7 @@ config("optimize_max") {
     configs = [ "//build/config/nacl:irt_optimize" ]
   } else {
     ldflags = common_optimize_on_ldflags
-    if (is_win) {
+    if (is_win && !is_mingw) {
       # Favor speed over size, /O2 must be before the common flags.
       # /O2 implies /Ot, /Oi, and /GF.
       cflags = [ "/O2" ] + common_optimize_on_cflags
@@ -2188,7 +2227,7 @@ config("optimize_speed") {
     configs = [ "//build/config/nacl:irt_optimize" ]
   } else {
     ldflags = common_optimize_on_ldflags
-    if (is_win) {
+    if (is_win && !is_mingw) {
       # Favor speed over size, /O2 must be before the common flags.
       # /O2 implies /Ot, /Oi, and /GF.
       cflags = [ "/O2" ] + common_optimize_on_cflags
@@ -2320,7 +2359,7 @@ config("win_pdbaltpath") {

 # Full symbols.
 config("symbols") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     if (is_clang) {
       cflags = [ "/Z7" ]  # Debug information in the .obj files.
     } else {
@@ -2372,7 +2411,8 @@ config("symbols") {
     # build-directory-independent output. pnacl and nacl-clang do support that
     # flag, so we can use use -g1 for pnacl and nacl-clang compiles.
     # gcc nacl is is_nacl && !is_clang, pnacl and nacl-clang are && is_clang.
-    if (!is_nacl || is_clang) {
+    # mingw cannot handle the size of the debug symbols generated.
+    if (!is_mingw && (!is_nacl || is_clang)) {
       cflags += [ "-g2" ]
     }

@@ -2423,7 +2463,7 @@ config("symbols") {
 # This config guarantees to hold symbol for stack trace which are shown to user
 # when crash happens in unittests running on buildbot.
 config("minimal_symbols") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     # Functions, files, and line tables only.
     cflags = []
     ldflags = [ "/DEBUG" ]
@@ -2482,7 +2522,7 @@ config("minimal_symbols") {
 # told to not generate debug information and the linker then just puts function
 # names in the final debug information.
 config("no_symbols") {
-  if (is_win) {
+  if (is_win && !is_mingw) {
     ldflags = [ "/DEBUG" ]

     # All configs using /DEBUG should include this:
@@ -2575,6 +2615,11 @@ buildflag_header("compiler_buildflags") {
 config("cet_shadow_stack") {
   if (enable_cet_shadow_stack && is_win) {
     assert(target_cpu == "x64")
-    ldflags = [ "/CETCOMPAT" ]
+    if(is_mingw){
+      ldflags = [ "-fcf-protection=full" ]
+      cflags = [ "-fcf-protection=full" ]
+    } else {
+      ldflags = [ "/CETCOMPAT" ]
+    }
   }
 }
diff --git a/config/linux/pkg-config.py b/config/linux/pkg-config.py
index 5adf70cc3..e28e798df 100644
--- a/config/linux/pkg-config.py
+++ b/config/linux/pkg-config.py
@@ -41,7 +41,11 @@ from optparse import OptionParser
 # Additionally, you can specify the option --atleast-version. This will skip
 # the normal outputting of a dictionary and instead print true or false,
 # depending on the return value of pkg-config for the given package.
-
+#
+# --pkg_config_libdir=<path> allows direct override
+# of the PKG_CONFIG_LIBDIR environment library.
+#
+# --full-path-libs causes lib names to include their full path.

 def SetConfigPath(options):
   """Set the PKG_CONFIG_LIBDIR environment variable.
@@ -105,11 +109,29 @@ def RewritePath(path, strip_prefix, sysroot):
     return path


+flag_regex = re.compile("(-.)(.+)")
+
+def FlagReplace(matchobj):
+  if matchobj.group(1) == '-I':
+     return matchobj.group(1) + subprocess.check_output([u'cygpath',u'-w',matchobj.group(2)]).strip().decode("utf-8")
+  if matchobj.group(1) == '-L':
+     return matchobj.group(1) + subprocess.check_output([u'cygpath',u'-w',matchobj.group(2)]).strip().decode("utf-8")
+  if matchobj.group(1) == '-l':
+     return matchobj.group(1) + matchobj.group(2) + '.lib'
+  return matchobj.group(0)
+
+def ConvertGCCToMSVC(flags):
+  """Rewrites GCC flags into MSVC flags."""
+  # need a better way to determine mingw vs msvc build
+  if 'win32' not in sys.platform or "GCC" in sys.version:
+    return flags
+  return [ flag_regex.sub(FlagReplace,flag) for flag in flags]
+
 def main():
   # If this is run on non-Linux platforms, just return nothing and indicate
   # success. This allows us to "kind of emulate" a Linux build from other
   # platforms.
-  if "linux" not in sys.platform:
+  if "linux" not in sys.platform and 'win32' not in sys.platform:
     print("[[],[],[],[],[]]")
     return 0

@@ -122,12 +144,15 @@ def main():
   parser.add_option('-a', action='store', dest='arch', type='string')
   parser.add_option('--system_libdir', action='store', dest='system_libdir',
                     type='string', default='lib')
+  parser.add_option('--pkg_config_libdir', action='store', dest='pkg_config_libdir',
+                    type='string')
   parser.add_option('--atleast-version', action='store',
                     dest='atleast_version', type='string')
   parser.add_option('--libdir', action='store_true', dest='libdir')
   parser.add_option('--dridriverdir', action='store_true', dest='dridriverdir')
   parser.add_option('--version-as-components', action='store_true',
                     dest='version_as_components')
+  parser.add_option('--full-path-libs', action='store_true', dest='full_path_libs')
   (options, args) = parser.parse_args()

   # Make a list of regular expressions to strip out.
@@ -144,6 +169,10 @@ def main():
   else:
     prefix = ''

+  # Override PKG_CONFIG_LIBDIR
+  if options.pkg_config_libdir:
+    os.environ['PKG_CONFIG_LIBDIR'] = options.pkg_config_libdir
+
   if options.atleast_version:
     # When asking for the return value, just run pkg-config and print the return
     # value, no need to do other work.
@@ -203,7 +232,7 @@ def main():
   # For now just split on spaces to get the args out. This will break if
   # pkgconfig returns quoted things with spaces in them, but that doesn't seem
   # to happen in practice.
-  all_flags = flag_string.strip().split(' ')
+  all_flags = ConvertGCCToMSVC(flag_string.strip().split(' '))


   sysroot = options.sysroot
@@ -220,7 +249,10 @@ def main():
       continue;

     if flag[:2] == '-l':
-      libs.append(RewritePath(flag[2:], prefix, sysroot))
+      library = RewritePath(flag[2:], prefix, sysroot)
+      # Skip math library on MSVC
+      if library != 'm.lib':
+        libs.append(library)
     elif flag[:2] == '-L':
       lib_dirs.append(RewritePath(flag[2:], prefix, sysroot))
     elif flag[:2] == '-I':
@@ -237,6 +269,14 @@ def main():
     else:
       cflags.append(flag)

+  if options.full_path_libs:
+    full_path_libs = []
+    for lib_dir in lib_dirs:
+      for lib in libs:
+        if os.path.isfile(lib_dir+"/"+lib):
+          full_path_libs.append(lib_dir+"/"+lib)
+    libs = full_path_libs
+
   # Output a GN array, the first one is the cflags, the second are the libs. The
   # JSON formatter prints GN compatible lists when everything is a list of
   # strings.
diff --git a/config/linux/pkg_config.gni b/config/linux/pkg_config.gni
index 428e44ac0..a0d2175ee 100644
--- a/config/linux/pkg_config.gni
+++ b/config/linux/pkg_config.gni
@@ -45,6 +45,9 @@ declare_args() {
   # in similar fashion by setting the `system_libdir` variable in the build's
   # args.gn file to 'lib' or 'lib64' as appropriate for the target architecture.
   system_libdir = "lib"
+
+  # Allow directly overriding the PKG_CONFIG_LIBDIR enviroment variable
+  pkg_config_libdir = ""
 }

 pkg_config_script = "//build/config/linux/pkg-config.py"
@@ -87,6 +90,17 @@ if (host_pkg_config != "") {
   host_pkg_config_args = pkg_config_args
 }

+if (pkg_config_libdir != "") {
+  pkg_config_args += [
+    "--pkg_config_libdir",
+    pkg_config_libdir,
+  ]
+  host_pkg_config_args += [
+    "--pkg_config_libdir",
+    pkg_config_libdir,
+  ]
+}
+
 template("pkg_config") {
   assert(defined(invoker.packages),
          "Variable |packages| must be defined to be a list in pkg_config.")
diff --git a/config/win/BUILD.gn b/config/win/BUILD.gn
index 813c72c05..b3a2051c1 100644
--- a/config/win/BUILD.gn
+++ b/config/win/BUILD.gn
@@ -46,7 +46,7 @@ declare_args() {
 # is applied to all targets. It is here to separate out the logic that is
 # Windows-only.
 config("compiler") {
-  if (current_cpu == "x86") {
+  if (current_cpu == "x86" && !is_mingw) {
     asmflags = [
       # When /safeseh is specified, the linker will only produce an image if it
       # can also produce a table of the image's safe exception handlers. This
@@ -57,27 +57,36 @@ config("compiler") {
     ]
   }

-  cflags = [
-    "/Gy",  # Enable function-level linking.
-    "/FS",  # Preserve previous PDB behavior.
-    "/bigobj",  # Some of our files are bigger than the regular limits.
-    "/utf-8",  # Assume UTF-8 by default to avoid code page dependencies.
-  ]
+  if(!is_mingw) {
+    cflags = [
+      "/Gy",  # Enable function-level linking.
+      "/FS",  # Preserve previous PDB behavior.
+      "/bigobj",  # Some of our files are bigger than the regular limits.
+      "/utf-8",  # Assume UTF-8 by default to avoid code page dependencies.
+    ]
+  } else {
+    cflags = [
+      "-Wa,-mbig-obj",
+      "-fno-keep-inline-dllexport"
+    ]
+  }

   if (is_clang) {
     cflags += [ "/Zc:twoPhase" ]
   }

-  # Force C/C++ mode for the given GN detected file type. This is necessary
-  # for precompiled headers where the same source file is compiled in both
-  # modes.
-  cflags_c = [ "/TC" ]
-  cflags_cc = [ "/TP" ]
+  if(!is_mingw) {
+    # Force C/C++ mode for the given GN detected file type. This is necessary
+    # for precompiled headers where the same source file is compiled in both
+    # modes.
+    cflags_c = [ "/TC" ]
+    cflags_cc = [ "/TP" ]

-  cflags += [
-    # Work around crbug.com/526851, bug in VS 2015 RTM compiler.
-    "/Zc:sizedDealloc-",
-  ]
+    cflags += [
+      # Work around crbug.com/526851, bug in VS 2015 RTM compiler.
+      "/Zc:sizedDealloc-",
+    ]
+  }

   if (is_clang) {
     # Required to make the 19041 SDK compatible with clang-cl.
@@ -150,7 +159,7 @@ config("compiler") {
     ldflags += [ "/lldignoreenv" ]
   }

-  if (!is_debug && !is_component_build) {
+  if (!is_debug && !is_component_build && !is_mingw) {
     # Enable standard linker optimizations like GC (/OPT:REF) and ICF in static
     # release builds.
     # Release builds always want these optimizations, so enable them explicitly.
@@ -175,17 +184,19 @@ config("compiler") {
     ldflags += [ "/PROFILE" ]
   }

-  # arflags apply only to static_libraries. The normal linker configs are only
-  # set for executable and shared library targets so arflags must be set
-  # elsewhere. Since this is relatively contained, we just apply them in this
-  # more general config and they will only have an effect on static libraries.
-  arflags = [
-    # "No public symbols found; archive member will be inaccessible." This
-    # means that one or more object files in the library can never be
-    # pulled in to targets that link to this library. It's just a warning that
-    # the source file is a no-op.
-    "/ignore:4221",
-  ]
+  if(!is_mingw){
+    # arflags apply only to static_libraries. The normal linker configs are only
+    # set for executable and shared library targets so arflags must be set
+    # elsewhere. Since this is relatively contained, we just apply them in this
+    # more general config and they will only have an effect on static libraries.
+    arflags = [
+      # "No public symbols found; archive member will be inaccessible." This
+      # means that one or more object files in the library can never be
+      # pulled in to targets that link to this library. It's just a warning that
+      # the source file is a no-op.
+      "/ignore:4221",
+    ]
+  }
 }

 # This is included by reference in the //build/config/compiler:runtime_library
@@ -294,29 +305,31 @@ config("sdk_link") {
     ldflags = [ "/MACHINE:ARM64" ]
   }

-  vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py",
-                                      [
-                                        visual_studio_path,
-                                        windows_sdk_path,
-                                        visual_studio_runtime_dirs,
-                                        current_os,
-                                        current_cpu,
-                                        "none",
-                                      ],
-                                      "scope")
-
-  vc_lib_path = vcvars_toolchain_data.vc_lib_path
-  if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) {
-    vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path
-  }
-  vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path
+  if(!is_mingw){
+    vcvars_toolchain_data = exec_script("../../toolchain/win/setup_toolchain.py",
+                                        [
+                                          visual_studio_path,
+                                          windows_sdk_path,
+                                          visual_studio_runtime_dirs,
+                                          current_os,
+                                          current_cpu,
+                                          "none",
+                                        ],
+                                        "scope")
+
+    vc_lib_path = vcvars_toolchain_data.vc_lib_path
+    if (defined(vcvars_toolchain_data.vc_lib_atlmfc_path)) {
+      vc_lib_atlmfc_path = vcvars_toolchain_data.vc_lib_atlmfc_path
+    }
+    vc_lib_um_path = vcvars_toolchain_data.vc_lib_um_path

-  lib_dirs = [
-    "$vc_lib_um_path",
-    "$vc_lib_path",
-  ]
-  if (defined(vc_lib_atlmfc_path)) {
-    lib_dirs += [ "$vc_lib_atlmfc_path" ]
+    lib_dirs = [
+      "$vc_lib_um_path",
+      "$vc_lib_path",
+    ]
+    if (defined(vc_lib_atlmfc_path)) {
+      lib_dirs += [ "$vc_lib_atlmfc_path" ]
+    }
   }
 }

@@ -324,19 +337,27 @@ config("sdk_link") {
 # targets who want different library configurations can remove this and specify
 # their own.
 config("common_linker_setup") {
-  ldflags = [
-    "/FIXED:NO",
-    "/ignore:4199",
-    "/ignore:4221",
-    "/NXCOMPAT",
-    "/DYNAMICBASE",
-  ]
-
-  if (win_linker_timing) {
-    ldflags += [
-      "/time",
-      "/verbose:incr",
+  if(is_mingw) {
+      # Enable DEP and ASLR
+    ldflags = [
+      "-Wl,-dynamicbase",
+      "-Wl,-nxcompat",
+     ]
+  } else {
+    ldflags = [
+      "/FIXED:NO",
+      "/ignore:4199",
+      "/ignore:4221",
+      "/NXCOMPAT",
+      "/DYNAMICBASE",
     ]
+
+    if (win_linker_timing) {
+      ldflags += [
+        "/time",
+        "/verbose:incr",
+      ]
+    }
   }
 }

@@ -373,7 +394,7 @@ config("cfi_linker") {
   # ASan and CFG leads to slow process startup. Chromium's test runner uses
   # lots of child processes, so this means things are really slow. Disable CFG
   # for now. https://crbug.com/846966
-  if (!is_debug && !is_asan) {
+  if (!is_debug && !is_asan && !is_mingw) {
     # Turn on CFG bitmap generation and CFG load config.
     ldflags = [ "/guard:cf" ]
   }
@@ -464,20 +485,22 @@ config("delayloads_not_for_child_dll") {
 # See https://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx for a reference of
 # what each value does.
 config("default_crt") {
-  if (is_component_build) {
-    # Component mode: dynamic CRT. Since the library is shared, it requires
-    # exceptions or will give errors about things not matching, so keep
-    # exceptions on.
-    configs = [ ":dynamic_crt" ]
-  } else {
-    if (current_os == "winuwp") {
-      # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
-      # contains a details explanation of what is happening with the Windows
-      # CRT in Visual Studio releases related to Windows store applications.
+  if(!is_mingw){
+    if (is_component_build) {
+      # Component mode: dynamic CRT. Since the library is shared, it requires
+      # exceptions or will give errors about things not matching, so keep
+      # exceptions on.
       configs = [ ":dynamic_crt" ]
     } else {
-      # Desktop Windows: static CRT.
-      configs = [ ":static_crt" ]
+      if (current_os == "winuwp") {
+        # https://blogs.msdn.microsoft.com/vcblog/2014/06/10/the-great-c-runtime-crt-refactoring/
+        # contains a details explanation of what is happening with the Windows
+        # CRT in Visual Studio releases related to Windows store applications.
+        configs = [ ":dynamic_crt" ]
+      } else {
+        # Desktop Windows: static CRT.
+        configs = [ ":static_crt" ]
+      }
     }
   }
 }
@@ -518,42 +541,54 @@ config("static_crt") {
 if (current_cpu == "x64") {
   # The number after the comma is the minimum required OS version.
   # 5.02 = Windows Server 2003.
-  subsystem_version_suffix = ",5.02"
+  subsystem_version_suffix = "5.02"
 } else if (current_cpu == "arm64") {
   # Windows ARM64 requires Windows 10.
-  subsystem_version_suffix = ",10.0"
+  subsystem_version_suffix = "10.0"
 } else {
   # 5.01 = Windows XP.
-  subsystem_version_suffix = ",5.01"
+  subsystem_version_suffix = "5.01"
 }

 config("console") {
-  ldflags = [ "/SUBSYSTEM:CONSOLE$subsystem_version_suffix" ]
+  if(is_mingw){
+    cflags = [ "-mconsole" ]
+    ldflags = [ "-Wl,--subsystem,console:$subsystem_version_suffix" ]
+  } else {
+    ldflags = [ "/SUBSYSTEM:CONSOLE,$subsystem_version_suffix" ]
+  }
 }
 config("windowed") {
-  ldflags = [ "/SUBSYSTEM:WINDOWS$subsystem_version_suffix" ]
+  if(is_mingw){
+    cflags = [ "-mwindows" ]
+    ldflags = [ "-Wl,--subsystem,windows:$subsystem_version_suffix" ]
+  } else {
+    ldflags = [ "/SUBSYSTEM:WINDOWS,$subsystem_version_suffix" ]
+  }
 }

 # Incremental linking ----------------------------------------------------------

 # Applies incremental linking or not depending on the current configuration.
 config("default_incremental_linking") {
-  # Enable incremental linking for debug builds and all component builds - any
-  # builds where performance is not job one.
-  # TODO(thakis): Always turn this on with lld, no reason not to.
-  if (is_debug || is_component_build) {
-    ldflags = [ "/INCREMENTAL" ]
-    if (use_lld) {
-      # lld doesn't use ilk files and doesn't really have an incremental link
-      # mode; the only effect of the flag is that the .lib file timestamp isn't
-      # updated if the .lib doesn't change.
-      # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise?
-      # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in
-      # lld.
-      ldflags += [ "/OPT:NOREF" ]
+  if(!is_mingw){
+    # Enable incremental linking for debug builds and all component builds - any
+    # builds where performance is not job one.
+    # TODO(thakis): Always turn this on with lld, no reason not to.
+    if (is_debug || is_component_build) {
+      ldflags = [ "/INCREMENTAL" ]
+      if (use_lld) {
+        # lld doesn't use ilk files and doesn't really have an incremental link
+        # mode; the only effect of the flag is that the .lib file timestamp isn't
+        # updated if the .lib doesn't change.
+        # TODO(thakis): Why pass /OPT:NOREF for lld, but not otherwise?
+        # TODO(thakis): /INCREMENTAL is on by default in link.exe, but not in
+        # lld.
+        ldflags += [ "/OPT:NOREF" ]
+      }
+    } else {
+      ldflags = [ "/INCREMENTAL:NO" ]
     }
-  } else {
-    ldflags = [ "/INCREMENTAL:NO" ]
   }
 }

@@ -565,6 +600,9 @@ config("unicode") {
     "_UNICODE",
     "UNICODE",
   ]
+  if(is_mingw) {
+    cflags = [ "-municode" ]
+  }
 }

 # Lean and mean ----------------------------------------------------------------
@@ -585,3 +623,21 @@ config("lean_and_mean") {
 config("nominmax") {
   defines = [ "NOMINMAX" ]
 }
+
+# Let unit tests see all "for_testing" dll symbols.
+config("export_all_symbols") {
+  if(is_win && is_mingw){
+    ldflags = [ "-Wl,--export-all-symbols" ]
+  }
+}
+
+# Workaround a Mingw ld bug where large debug symbol data
+# causes the produced executable to be corrupted
+# https://stackoverflow.com/questions/22261539/ld-exe-crashing-in-mingw
+# this affects mksnapshot and v8 component.
+
+config("strip_all_symbols_at_link_time") {
+  if(is_win && is_mingw){
+    ldflags = [ "-Wl,--strip-all" ]
+  }
+}
diff --git a/config/win/manifest.gni b/config/win/manifest.gni
index e2115083f..c6bdef8fb 100644
--- a/config/win/manifest.gni
+++ b/config/win/manifest.gni
@@ -85,12 +85,14 @@ if (is_win) {
       foreach(i, rebase_path(invoker.sources, root_build_dir)) {
         manifests += [ "/manifestinput:" + i ]
       }
-      ldflags = [
-                  "/manifest:embed",
+      if(!is_mingw){
+        ldflags = [
+                    "/manifest:embed",

-                  # We handle UAC by adding explicit .manifest files instead.
-                  "/manifestuac:no",
-                ] + manifests
+                    # We handle UAC by adding explicit .manifest files instead.
+                    "/manifestuac:no",
+                  ] + manifests
+      }
     }

     # This source set only exists to add a dep on the invoker's deps and to
diff --git a/config/x64.gni b/config/x64.gni
index 9e86979cb..ca8f47501 100644
--- a/config/x64.gni
+++ b/config/x64.gni
@@ -16,7 +16,7 @@ if (current_cpu == "x64") {
     x64_arch = ""
   }

-  if ((is_posix && !is_apple) || is_fuchsia) {
+  if ((is_posix && !is_apple) || is_fuchsia || is_mingw) {
     if (x64_arch == "") {
       x64_arch = "x86-64"
     }
diff --git a/toolchain/gcc_solink_wrapper.py b/toolchain/gcc_solink_wrapper.py
index 39aef4d1e..7e83b058a 100644
--- a/toolchain/gcc_solink_wrapper.py
+++ b/toolchain/gcc_solink_wrapper.py
@@ -18,10 +18,11 @@ import sys

 import wrapper_utils

-
 def CollectSONAME(args):
   """Replaces: readelf -d $sofile | grep SONAME"""
   toc = ''
+  if ("GCC" in sys.version and sys.platform=='win32'): # Mingw's readelf doesn't work on PE files
+    return 0, toc
   readelf = subprocess.Popen(wrapper_utils.CommandToRun(
       [args.readelf, '-d', args.sofile]),
                              stdout=subprocess.PIPE,
@@ -36,6 +37,10 @@ def CollectSONAME(args):
 def CollectDynSym(args):
   """Replaces: nm --format=posix -g -D -p $sofile | cut -f1-2 -d' '"""
   toc = ''
+
+  if ("GCC" in sys.version and sys.platform=='win32'): # Mingw's nm doesn't work on PE/COFF files
+    return 0, toc
+
   nm = subprocess.Popen(wrapper_utils.CommandToRun(
       [args.nm, '--format=posix', '-g', '-D', '-p', args.sofile]),
                         stdout=subprocess.PIPE,
@@ -94,6 +99,9 @@ def main():
                       help='The strip binary to run',
                       metavar='PATH')
   parser.add_argument('--dwp', help='The dwp binary to run', metavar='PATH')
+  parser.add_argument('--objcopy',
+                      help='The objcopy binary to run',
+                      metavar='PATH')
   parser.add_argument('--sofile',
                       required=True,
                       help='Shared object file produced by linking command',
@@ -183,8 +191,18 @@ def main():

   # Finally, strip the linked shared object file (if desired).
   if args.strip:
+    if args.objcopy:
+      result = subprocess.call(wrapper_utils.CommandToRun(
+          [args.objcopy, '--only-keep-debug', args.sofile, args.output + '.debug']))
+      if result != 0:
+        return result
     result = subprocess.call(wrapper_utils.CommandToRun(
         [args.strip, '-o', args.output, args.sofile]))
+    if result != 0:
+      return result
+    if args.objcopy:
+      result = subprocess.call(wrapper_utils.CommandToRun(
+          [args.objcopy, '--add-gnu-debuglink', args.output + '.debug',args.output]))

   if dwp_proc:
     dwp_result = dwp_proc.wait()
@@ -193,6 +211,5 @@ def main():

   return result

-
 if __name__ == "__main__":
   sys.exit(main())
diff --git a/toolchain/gcc_toolchain.gni b/toolchain/gcc_toolchain.gni
index 9418f5cea..4484c2e76 100644
--- a/toolchain/gcc_toolchain.gni
+++ b/toolchain/gcc_toolchain.gni
@@ -59,6 +59,7 @@ if (enable_resource_allowlist_generation) {
 #  - cc
 #  - cxx
 #  - ld
+#  - rc (mingw only)
 #
 # Optional parameters that control the tools:
 #
@@ -111,7 +112,9 @@ template("gcc_toolchain") {
     assert(defined(invoker.cc), "gcc_toolchain() must specify a \"cc\" value")
     assert(defined(invoker.cxx), "gcc_toolchain() must specify a \"cxx\" value")
     assert(defined(invoker.ld), "gcc_toolchain() must specify a \"ld\" value")
-
+    if(is_mingw){
+      assert(defined(invoker.rc), "gcc_toolchain() must specify a \"rc\" value")
+    }
     # This define changes when the toolchain changes, forcing a rebuild.
     # Nothing should ever use this define.
     if (defined(invoker.rebuild_define)) {
@@ -269,15 +272,19 @@ template("gcc_toolchain") {
     asm = asm_prefix + invoker.cc
     ar = invoker.ar
     ld = "$goma_ld${invoker.ld}"
-    if (defined(invoker.readelf)) {
-      readelf = invoker.readelf
-    } else {
-      readelf = "readelf"
-    }
-    if (defined(invoker.nm)) {
-      nm = invoker.nm
+    if(!is_mingw){
+      if (defined(invoker.readelf)) {
+        readelf = invoker.readelf
+      } else {
+        readelf = "readelf"
+      }
+      if (defined(invoker.nm)) {
+        nm = invoker.nm
+      } else {
+        nm = "nm"
+      }
     } else {
-      nm = "nm"
+      rc = invoker.rc
     }
     if (defined(invoker.dwp)) {
       dwp_switch = " --dwp=\"${invoker.dwp}\""
@@ -285,6 +292,7 @@ template("gcc_toolchain") {
       dwp_switch = ""
     }

+
     if (defined(invoker.shlib_extension)) {
       default_shlib_extension = invoker.shlib_extension
     } else {
@@ -362,6 +370,16 @@ template("gcc_toolchain") {
       outputs = [ "$object_subdir/{{source_name_part}}.o" ]
     }

+    if(is_mingw){
+      tool("rc") {
+        depfile = "{{output}}.d"
+        command = "$rc -i {{source}} -o {{output}}"
+        depsformat = "gcc"
+        description = "RC {{output}}"
+        outputs = [ "$object_subdir/{{source_name_part}}.o" ]
+      }
+    }
+
     tool("asm") {
       # For GCC we can just use the C compiler to compile assembly.
       depfile = "{{output}}.d"
@@ -422,8 +440,6 @@ template("gcc_toolchain") {
       # .TOC file, overwrite it, otherwise, don't change it.
       tocfile = sofile + ".TOC"

-      link_command = "$ld -shared -Wl,-soname=\"$soname\" {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\""
-
       # Generate a map file to be used for binary size analysis.
       # Map file adds ~10% to the link time on a z620.
       # With target_os="android", libchrome.so.map.gz is ~20MB.
@@ -433,13 +449,30 @@ template("gcc_toolchain") {
         map_switch = " --map-file \"$map_file\""
       }

-      assert(defined(readelf), "to solink you must have a readelf")
-      assert(defined(nm), "to solink you must have an nm")
       strip_switch = ""
       if (defined(invoker.strip)) {
         strip_switch = "--strip=${invoker.strip} "
       }

+      mingw_flags = ""
+      if(is_mingw){
+        # Have MinGW linker generate a .def file and a .a import library
+        mingw_flags = " -Wl,--dll -Wl,--output-def=\"$sofile\".def -Wl,--out-implib=\"$sofile\".a "
+        readelf = ""
+        if (defined(invoker.readelf)) {
+          readelf = "${invoker.readelf} "
+        }
+        nm = ""
+        if (defined(invoker.nm)) {
+          readelf = "${invoker.nm} "
+        }
+      } else {
+        assert(defined(readelf), "to solink you must have a readelf")
+        assert(defined(nm), "to solink you must have an nm")
+      }
+
+      link_command = "$ld -shared -Wl,-soname=\"$soname\" ${mingw_flags} {{ldflags}}${extra_ldflags} -o \"$unstripped_sofile\" @\"$rspfile\""
+
       # This needs a Python script to avoid using a complex shell command
       # requiring sh control structures, pipelines, and POSIX utilities.
       # The host might not have a POSIX shell and utilities (e.g. Windows).
diff --git a/toolchain/win/BUILD.gn b/toolchain/win/BUILD.gn
index a8137526d..d512605e2 100644
--- a/toolchain/win/BUILD.gn
+++ b/toolchain/win/BUILD.gn
@@ -10,6 +10,7 @@ import("//build/toolchain/cc_wrapper.gni")
 import("//build/toolchain/goma.gni")
 import("//build/toolchain/rbe.gni")
 import("//build/toolchain/toolchain.gni")
+import("//build/toolchain/gcc_toolchain.gni")

 # Should only be running on Windows.
 assert(is_win)
@@ -51,13 +52,15 @@ if (current_toolchain == default_toolchain) {
   } else {
     configuration_name = "Release"
   }
-  exec_script("../../vs_toolchain.py",
-              [
-                "copy_dlls",
-                rebase_path(root_build_dir),
-                configuration_name,
-                target_cpu,
-              ])
+  if(!is_mingw){
+    exec_script("../../vs_toolchain.py",
+                [
+                  "copy_dlls",
+                  rebase_path(root_build_dir),
+                  configuration_name,
+                  target_cpu,
+                ])
+  }
 }

 if (host_os == "win") {
@@ -532,3 +535,29 @@ if (target_os == "winuwp") {
     }
   }
 }
+
+template("mingw_toolchain") {
+  gcc_toolchain("mingw_" + target_name) {
+    forward_variables_from(invoker, "*")
+    cc = "gcc"
+    cxx = "g++"
+    ar = "ar"
+    ld = cxx
+    if(is_mingw){
+      rc = "windres"
+    }
+    strip = "strip"
+    executable_extension = ".exe"
+    toolchain_args = {
+      current_cpu = target_name
+      current_os = "win"
+      is_clang = false
+    }
+  }
+}
+
+mingw_toolchain("x64") {
+}
+
+mingw_toolchain("x86") {
+}
diff --git a/util/lastchange.py b/util/lastchange.py
index 874870ad5..a4fc0be8d 100644
--- a/util/lastchange.py
+++ b/util/lastchange.py
@@ -191,7 +191,10 @@ def GetGitTopDirectory(source_dir):
   Returns:
     The output of "git rev-parse --show-toplevel" as a string
   """
-  return _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel'])
+  directory = _RunGitCommand(source_dir, ['rev-parse', '--show-toplevel'])
+  if "GCC" in sys.version and sys.platform=='win32':
+    return subprocess.check_output(["cygpath", "-w", directory]).strip(b"\n").decode()
+  return directory


 def WriteIfChanged(file_name, contents):
diff --git a/win/BUILD.gn b/win/BUILD.gn
index d449f5925..558e04229 100644
--- a/win/BUILD.gn
+++ b/win/BUILD.gn
@@ -16,7 +16,7 @@ windows_manifest("default_exe_manifest") {
   ]
 }

-if (is_win) {
+if (is_win && !is_mingw) {
   assert(host_os != "mac" || target_cpu != "x86",
          "Windows cross-builds from Mac must be 64-bit.")

@@ -92,7 +92,7 @@ if (is_win) {

   group("runtime_libs") {
     data = []
-    if (is_component_build) {
+    if (is_component_build && !is_mingw) {
       # Copy the VS runtime DLLs into the isolate so that they don't have to be
       # preinstalled on the target machine. The debug runtimes have a "d" at
       # the end.
