misc WSL fixes draft
authorTed Mielczarek <ted@mielczarek.org>
Thu, 14 Sep 2017 06:56:25 -0400
changeset 664872 e3baad5e1bddd36ab635816a8ee1458442b0ee0b
parent 664871 1e45c016412a79289e9bc1bf314abf2851ea2d9f
child 664873 d5e3d1d4c9184f323c3a72d621ccef13ff0b5315
push id79836
push userbmo:ted@mielczarek.org
push dateThu, 14 Sep 2017 14:29:42 +0000
milestone57.0a1
misc WSL fixes MozReview-Commit-ID: IjxEqPAYHXZ
.cargo/config.in
build/autoconf/nspr-build.m4
build/moz.configure/util.configure
build/moz.configure/windows.configure
config/config.mk
config/make-stl-wrappers.py
config/rules.mk
js/src/old-configure.in
old-configure.in
python/mozbuild/mozbuild/backend/base.py
python/mozbuild/mozbuild/backend/recursivemake.py
python/mozbuild/mozpack/path.py
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -1,6 +1,6 @@
 [source.crates-io]
 registry = 'https://github.com/rust-lang/crates.io-index'
 replace-with = 'vendored-sources'
 
 [source.vendored-sources]
-directory = '@top_srcdir@/third_party/rust'
+directory = '@top_srcdir_win@/third_party/rust'
--- a/build/autoconf/nspr-build.m4
+++ b/build/autoconf/nspr-build.m4
@@ -155,17 +155,17 @@ if test -n "$MOZ_SYSTEM_NSPR" -o -n "$NS
                  #endif],
                 ,
                 AC_MSG_ERROR([system NSPR does not support PR_UINT64 or including prtypes.h does not provide it]))
     CFLAGS=$_SAVE_CFLAGS
     NSPR_INCLUDE_DIR=`echo ${NSPR_CFLAGS} | sed -e 's/.*-I\([^ ]*\).*/\1/'`
     NSPR_LIB_DIR=`echo ${NSPR_LIBS} | sed -e 's/.*-L\([^ ]*\).*/\1/'`
 elif test -z "$JS_POSIX_NSPR"; then
     NSPR_INCLUDE_DIR="${DIST}/include/nspr"
-    NSPR_CFLAGS="-I${NSPR_INCLUDE_DIR}"
+    NSPR_CFLAGS='-I$(DIST)/include/nspr'
     if test -n "$GNU_CC"; then
         if test -n "$MOZ_FOLD_LIBS"; then
            NSPR_LIB_DIR=${DIST}/lib
         else
            NSPR_LIB_DIR=${DIST}/bin
         fi
         NSPR_LIBS="-L${NSPR_LIB_DIR} -lnspr${NSPR_VERSION} -lplc${NSPR_VERSION} -lplds${NSPR_VERSION}"
     else
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -165,17 +165,17 @@ normalize_path = normalize_path()
 
 # When building under WSL, map `path` to a Windows-native path. On other
 # platforms, this function is a no-op.
 def win_path():
     if host_is_wsl_check():
         def win_path(path):
             if path.startswith('/'):
                 if not path.startswith('/mnt'):
-                    die("Can't convert a non-drvfs path to Windows format: %s" % path)
+                    configure_error("Can't convert a non-drvfs path to Windows format: %s" % path)
                 _, _, drive, rest = path.split('/', 3)
                 return drive + ':/' + rest
             else:
                 return path
     else:
         def win_path(path):
             return path
     return win_path
--- a/build/moz.configure/windows.configure
+++ b/build/moz.configure/windows.configure
@@ -272,60 +272,78 @@ def dia_sdk_dir(vc_path, c_compiler):
             if path:
                 path = os.path.normpath(os.path.join(path, 'DIA SDK'))
         if isdir(path):
             return path
 
 
 @depends(vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir, dia_sdk_dir)
 @imports('os')
-def include_path(vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
+def include_paths(vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
     if not vc_path:
         return
     atlmfc_dir = os.path.join(vc_path, 'atlmfc', 'include')
     if not os.path.isdir(atlmfc_dir):
         die('Cannot find the ATL/MFC headers in the Visual C++ directory (%s). '
             'Please install them.' % vc_path)
 
     winrt_dir = os.path.join(windows_sdk_dir.include, 'winrt')
     if not os.path.isdir(winrt_dir):
         die('Cannot find the WinRT headers in the Windows SDK directory (%s). '
             'Please install them.' % windows_sdk_dir.path)
 
     includes = []
     include_env = os.environ.get('INCLUDE')
     if include_env:
-        includes.append(include_env)
+        log.info('INCLUDE: %s' % include_env)
+        includes.extend(include_env.split(os.pathsep))
     includes.extend((
         os.path.join(vc_path, 'include'),
         atlmfc_dir,
         os.path.join(windows_sdk_dir.include, 'shared'),
         os.path.join(windows_sdk_dir.include, 'um'),
         winrt_dir,
         os.path.join(ucrt_sdk_dir.include, 'ucrt'),
     ))
     if dia_sdk_dir:
         includes.append(os.path.join(dia_sdk_dir, 'include'))
+    return [win_path(i) for i in includes]
+
+@depends(include_paths, host_is_wsl)
+@imports('os')
+def include_path(include_paths, host_is_wsl):
+    if not include_paths:
+        return
     # Set in the environment for old-configure
-    includes = os.pathsep.join(includes)
-    os.environ['INCLUDE'] = includes
+    includes = os.pathsep.join(normalize_path(p) for p in include_paths)
+    if not host_is_wsl:
+        os.environ['INCLUDE'] = includes
     return includes
 
 set_config('INCLUDE', include_path)
 
-@depends(include_path, host_is_wsl)
-@imports('os')
-def include_cflags(include_path, host_is_wsl):
-    if include_path and host_is_wsl:
-        return ['-I' + win_path(path) for path in include_path.split(os.pathsep)]
-    return []
+@depends(include_paths, host_is_wsl)
+def win_include_paths(include_paths, host_is_wsl):
+    if include_paths and host_is_wsl:
+        return ';'.join(include_paths)
+
+set_config('WININCLUDE', win_include_paths)
+
+@depends(include_paths, host_is_wsl)
+@imports(_from='mozbuild.shellutil', _import='quote')
+def include_cflags(include_paths, host_is_wsl):
+    if include_paths and host_is_wsl:
+        return ['-I' + quote(path) for path in include_paths]
+
+set_config('INCLUDE_CFLAGS', include_cflags)
+
 
 @depends(target, c_compiler, vc_path, valid_windows_sdk_dir, valid_ucrt_sdk_dir, dia_sdk_dir)
 @imports('os')
-def lib_path(target, c_compiler, vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
+def lib_paths(target, c_compiler, vc_path, windows_sdk_dir, ucrt_sdk_dir, dia_sdk_dir):
     if not vc_path:
         return
     sdk_target = {
         'x86': 'x86',
         'x86_64': 'x64',
         'arm': 'arm',
     }.get(target.cpu)
 
@@ -362,23 +380,38 @@ def lib_path(target, c_compiler, vc_path
         atlmfc_dir,
         os.path.join(windows_sdk_dir.lib, 'um', sdk_target),
         os.path.join(ucrt_sdk_dir.lib, 'ucrt', sdk_target),
     ))
     if dia_sdk_dir:
         # For some reason the DIA SDK still uses the old-style targets
         # even in a newer MSVC.
         libs.append(os.path.join(dia_sdk_dir, 'lib', *old_target))
+    return [win_path(l) for l in libs]
+
+@depends(lib_paths, host_is_wsl)
+@imports('os')
+def lib_path(lib_paths, host_is_wsl):
+    if not lib_paths:
+        return
     # Set in the environment for old-configure
-    libs = os.pathsep.join(libs)
-    os.environ['LIB'] = libs
+    libs = os.pathsep.join(normalize_path(p) for p in lib_paths)
+    if not host_is_wsl:
+        os.environ['LIB'] = libs
     return libs
 
 set_config('LIB', lib_path)
 
+@depends(lib_paths, host_is_wsl)
+@imports(_from='mozbuild.shellutil', _import='quote')
+def libs_ldflags(lib_paths, host_is_wsl):
+    if lib_paths and host_is_wsl:
+        return ['-LIBPATH:' + quote(path) for path in lib_paths]
+
+set_config('LIBS_LDFLAGS', libs_ldflags)
 
 option(env='MT', nargs=1, help='Path to the Microsoft Manifest Tool')
 
 @depends(valid_windows_sdk_dir, valid_ucrt_sdk_dir)
 @imports(_from='os', _import='environ')
 @imports('platform')
 def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir):
     if not valid_windows_sdk_dir:
@@ -440,30 +473,41 @@ add_old_configure_assignment('LINK', lin
 @imports('os')
 def alter_path(sdk_bin_path):
     path = os.pathsep.join(sdk_bin_path)
     os.environ['PATH'] = path
     return path
 
 set_config('PATH', alter_path)
 
+@depends(alter_path, when=host_is_wsl)
+@imports('os')
+def wsl_path(path):
+    return ';'.join(win_path(p) for p in path.split(os.pathsep) if p.startswith('/mnt/'))
+
+set_config('WINPATH', wsl_path)
+
 check_prog('MAKECAB', ('makecab.exe',))
 
 @depends(c_compiler, using_sccache)
 def need_showincludes_prefix(info, using_sccache):
     # sccache does its own -showIncludes prefix checking.
     if info.type in ('clang-cl', 'msvc') and not using_sccache:
         return True
 
-@depends(c_compiler, include_cflags, when=need_showincludes_prefix)
+@depends(c_compiler, include_paths, when=need_showincludes_prefix)
 @imports(_from='re', _import='compile', _as='re_compile')
-def msvc_showincludes_prefix(c_compiler, include_cflags):
+def msvc_showincludes_prefix(c_compiler, include_paths):
     pattern = re_compile(br'^([^:]*:.*[ :] )(.*\\stdio.h)$')
+    if include_paths:
+        extra = ['-I' + path for path in include_paths]
+    else:
+        extra = []
     output = try_invoke_compiler([c_compiler.compiler], 'C', '#include <stdio.h>\n',
-                                 ['-nologo', '-c', '-Fonul', '-showIncludes'] + include_cflags)
+                                 ['-nologo', '-c', '-Fonul', '-showIncludes'] + extra)
     for line in output.splitlines():
         if line.endswith(b'\\stdio.h'):
             m = pattern.match(line)
             if m:
                 return m.group(1)
     # We should have found the prefix and returned earlier
     die('Cannot find cl -showIncludes prefix.')
 
--- a/config/config.mk
+++ b/config/config.mk
@@ -248,20 +248,20 @@ MY_CONFIG	:= $(DEPTH)/config/myconfig.mk
 MY_RULES	:= $(DEPTH)/config/myrules.mk
 
 #
 # Default command macros; can be overridden in <arch>.mk.
 #
 CCC = $(CXX)
 
 INCLUDES = \
-  -I$(srcdir) \
-  -I$(CURDIR) \
+  -I$(srcdir_rel) \
+  -I. \
   $(LOCAL_INCLUDES) \
-  -I$(ABS_DIST)/include \
+  -I$(DIST)/include \
   $(NULL)
 
 ifndef IS_GYP_DIR
 # NSPR_CFLAGS and NSS_CFLAGS must appear ahead of the other flags to avoid Linux
 # builds wrongly picking up system NSPR/NSS header files.
 OS_INCLUDES := \
   $(NSPR_CFLAGS) $(NSS_CFLAGS) \
   $(MOZ_JPEG_CFLAGS) \
@@ -325,28 +325,28 @@ endif # CLANG_CL
 
 # Use warnings-as-errors if ALLOW_COMPILER_WARNINGS is not set to 1 (which
 # includes the case where it's undefined).
 ifneq (1,$(ALLOW_COMPILER_WARNINGS))
 CXXFLAGS += $(WARNINGS_AS_ERRORS)
 CFLAGS   += $(WARNINGS_AS_ERRORS)
 endif # ALLOW_COMPILER_WARNINGS
 
-COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS) $(_DEPEND_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(MK_COMPILE_DEFINES)
-COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS) $(_DEPEND_CFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(MK_COMPILE_DEFINES)
+COMPILE_CFLAGS	= $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDE_CFLAGS) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CFLAGS) $(_DEPEND_CFLAGS) $(CFLAGS) $(MOZBUILD_CFLAGS) $(MK_COMPILE_DEFINES)
+COMPILE_CXXFLAGS = $(if $(DISABLE_STL_WRAPPING),,$(STL_FLAGS)) $(VISIBILITY_FLAGS) $(DEFINES) $(INCLUDE_CFLAGS) $(INCLUDES) $(OS_INCLUDES) $(DSO_CFLAGS) $(DSO_PIC_CFLAGS) $(RTL_FLAGS) $(OS_COMPILE_CXXFLAGS) $(_DEPEND_CFLAGS) $(CXXFLAGS) $(MOZBUILD_CXXFLAGS) $(MK_COMPILE_DEFINES)
 COMPILE_CMFLAGS = $(OS_COMPILE_CMFLAGS) $(MOZBUILD_CMFLAGS)
 COMPILE_CMMFLAGS = $(OS_COMPILE_CMMFLAGS) $(MOZBUILD_CMMFLAGS)
 ASFLAGS += $(MOZBUILD_ASFLAGS)
 
 ifndef CROSS_COMPILE
 HOST_CFLAGS += $(RTL_FLAGS)
 endif
 
-HOST_CFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CFLAGS)
-HOST_CXXFLAGS += $(HOST_DEFINES) $(MOZBUILD_HOST_CXXFLAGS)
+HOST_CFLAGS += $(HOST_DEFINES) $(INCLUDE_CFLAGS) $(MOZBUILD_HOST_CFLAGS)
+HOST_CXXFLAGS += $(HOST_DEFINES) $(INCLUDE_CFLAGS) $(MOZBUILD_HOST_CXXFLAGS)
 
 # We only add color flags if neither the flag to disable color
 # (e.g. "-fno-color-diagnostics" nor a flag to control color
 # (e.g. "-fcolor-diagnostics=never") is present.
 define colorize_flags
 ifeq (,$(filter $(COLOR_CFLAGS:-f%=-fno-%),$$(1))$(findstring $(COLOR_CFLAGS),$$(1)))
 $(1) += $(COLOR_CFLAGS)
 endif
@@ -544,17 +544,17 @@ CREATE_PRECOMPLETE_CMD = $(PYTHON) $(abs
 # MDDEPDIR is the subdirectory where dependency files are stored
 MDDEPDIR := .deps
 
 EXPAND_LIBS_EXEC = $(PYTHON) $(MOZILLA_DIR)/config/expandlibs_exec.py
 EXPAND_LIBS_GEN = $(PYTHON) $(MOZILLA_DIR)/config/expandlibs_gen.py
 EXPAND_AR = $(EXPAND_LIBS_EXEC) --extract -- $(AR)
 EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselist -- $(CC)
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
-EXPAND_LINK = $(EXPAND_LIBS_EXEC) --uselist -- $(LINK)
+EXPAND_LINK = $(EXPAND_LIBS_EXEC) --uselist -- "$(LINK)"
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
 
 # $(call CHECK_SYMBOLS,lib,PREFIX,dep_name,test)
 # Checks that the given `lib` doesn't contain dependency on symbols with a
--- a/config/make-stl-wrappers.py
+++ b/config/make-stl-wrappers.py
@@ -1,21 +1,22 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 from __future__ import print_function
 import os, re, string, sys
 from mozbuild.util import FileAvoidWrite
+import mozpack.path as mozpath
 
 def find_in_path(file, searchpath):
     for dir in searchpath.split(os.pathsep):
         f = os.path.join(dir, file)
         if os.path.exists(f):
             return f
-    return ''
+    raise Exception('Header not found: %s' % file)
 
 def header_path(header, compiler):
     if compiler == 'gcc':
         # we use include_next on gcc
         return header
     elif compiler == 'msvc':
         return find_in_path(header, os.environ.get('INCLUDE', ''))
     else:
@@ -34,17 +35,17 @@ def main(outdir, compiler, template_file
     for header in open(header_list_file, 'r'):
         header = header.rstrip()
         if 0 == len(header) or is_comment(header):
             continue
 
         path = header_path(header, compiler)
         with FileAvoidWrite(os.path.join(outdir, header)) as f:
             f.write(string.Template(template).substitute(HEADER=header,
-                                                         HEADER_PATH=path))
+                                                         HEADER_PATH=mozpath.win_path(path)))
 
 
 if __name__ == '__main__':
     if 5 != len(sys.argv):
         print("""Usage:
   python {0} OUT_DIR ('msvc'|'gcc') TEMPLATE_FILE HEADER_LIST_FILE
 """.format(sys.argv[0]), file=sys.stderr)
         sys.exit(1)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -47,17 +47,21 @@ EXEC			= exec
 # prints out failed commands anyway, so ELOG just makes things worse by
 # forcing shell invocations.
 ifneq (,$(findstring -s, $(filter-out --%, $(MAKEFLAGS))))
   ELOG := $(EXEC) sh $(BUILD_TOOLS)/print-failed-commands.sh
 else
   ELOG :=
 endif # -s
 
+ifndef HOST_IS_WSL
 _VPATH_SRCS = $(abspath $<)
+else
+_VPATH_SRCS = $<
+endif
 
 ################################################################################
 # Testing frameworks support
 ################################################################################
 
 testxpcobjdir = $(DEPTH)/_tests/xpcshell
 
 ifdef ENABLE_TESTS
@@ -358,19 +362,19 @@ ifdef LD_VERSION_SCRIPT
 EXTRA_DSO_LDOPTS += -Wl,--version-script,$(LD_VERSION_SCRIPT)
 EXTRA_DEPS += $(LD_VERSION_SCRIPT)
 endif
 endif
 
 ifdef SYMBOLS_FILE
 ifeq ($(OS_TARGET),WINNT)
 ifndef GNU_CC
-EXTRA_DSO_LDOPTS += -DEF:$(call normalizepath,$(SYMBOLS_FILE))
+EXTRA_DSO_LDOPTS += -DEF:$(SYMBOLS_FILE)
 else
-EXTRA_DSO_LDOPTS += $(call normalizepath,$(SYMBOLS_FILE))
+EXTRA_DSO_LDOPTS += $(SYMBOLS_FILE)
 endif
 else
 ifdef GCC_USE_GNU_LD
 EXTRA_DSO_LDOPTS += -Wl,--version-script,$(SYMBOLS_FILE)
 else
 ifeq ($(OS_TARGET),Darwin)
 EXTRA_DSO_LDOPTS += -Wl,-exported_symbols_list,$(SYMBOLS_FILE)
 endif
@@ -573,29 +577,29 @@ endef
 #
 # PROGRAM = Foo
 # creates OBJS, links with LIBS to create Foo
 #
 $(PROGRAM): $(PROGOBJS) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 	@$(RM) $@.manifest
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
-	$(EXPAND_LINK) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+	$(EXPAND_LINK) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE)  $(LIBS_LDFLAGS) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		if test -f '$(srcdir)/$@.manifest'; then \
 			echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
-			$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
+			"$(MT)" -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		else \
 			echo 'Embedding manifest from $@.manifest'; \
-			$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
+			"$(MT)" -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		fi; \
 	elif test -f '$(srcdir)/$@.manifest'; then \
 		echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
-		$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
+		"$(MT)" -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;1; \
 	fi
 endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
 endif
 else # !WINNT || GNU_CC
@@ -645,17 +649,17 @@ endif
 # Foo.o (from either Foo.c or Foo.cpp).
 #
 # SIMPLE_PROGRAMS = Foo Bar
 # creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
 #
 $(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
-	$(EXPAND_LINK) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+	$(EXPAND_LINK) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $<  $(LIBS_LDFLAGS) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
 	$(call EXPAND_CC_OR_CXX,$@) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS)
@@ -667,17 +671,17 @@ ifdef ENABLE_STRIP
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
 
 $(HOST_SIMPLE_PROGRAMS): host_%$(HOST_BIN_SUFFIX): host_%.$(OBJ_SUFFIX) $(HOST_LIBS) $(HOST_EXTRA_DEPS) $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 ifeq (WINNT_,$(HOST_OS_ARCH)_$(GNU_CC))
-	$(EXPAND_LIBS_EXEC) -- $(LINK) -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
+	$(EXPAND_LIBS_EXEC) -- "$(LINK)" -NOLOGO -OUT:$@ -PDB:$(HOST_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LIBS_LDFLAGS) $(HOST_LIBS) $(HOST_EXTRA_LIBS)
 else
 ifneq (,$(HOST_CPPSRCS)$(USE_HOST_CXX))
 	$(EXPAND_LIBS_EXEC) -- $(HOST_CXX) $(HOST_OUTOPTION)$@ $(HOST_CXXFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
 else
 	$(EXPAND_LIBS_EXEC) -- $(HOST_CC) $(HOST_OUTOPTION)$@ $(HOST_CFLAGS) $(INCLUDES) $< $(HOST_LIBS) $(HOST_EXTRA_LIBS)
 endif
 endif
 ifndef CROSS_COMPILE
@@ -717,33 +721,33 @@ endif
 # symlinks back to the originals. The symlinks are a no-op for stabs debugging,
 # so no need to conditionalize on OS version or debugging format.
 
 $(SHARED_LIBRARY): $(OBJS) $(RESFILE) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
 	$(REPORT_BUILD)
 ifndef INCREMENTAL_LINKER
 	$(RM) $@
 endif
-	$(EXPAND_MKSHLIB) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
+	$(EXPAND_MKSHLIB) $(LIBS_LDFLAGS) $(SHLIB_LDSTARTFILE) $(OBJS) $(SUB_SHLOBJS) $(RESFILE) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(RUST_STATIC_LIB_FOR_SHARED_LIB) $(SHARED_LIBS) $(EXTRA_DSO_LDOPTS) $(MOZ_GLUE_LDFLAGS) $(EXTRA_LIBS) $(OS_LIBS) $(SHLIB_LDENDFILE)
 	$(call CHECK_BINARY,$@)
 
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
 ifdef MSMANIFEST_TOOL
 ifdef EMBED_MANIFEST_AT
 	@if test -f $@.manifest; then \
 		if test -f '$(srcdir)/$@.manifest'; then \
 			echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
-			$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+			"$(MT)" -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		else \
 			echo 'Embedding manifest from $@.manifest'; \
-			$(MT) -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+			"$(MT)" -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 		fi; \
 	elif test -f '$(srcdir)/$@.manifest'; then \
 		echo 'Embedding manifest from $(srcdir)/$@.manifest'; \
-		$(MT) -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
+		"$(MT)" -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' -OUTPUTRESOURCE:$@\;$(EMBED_MANIFEST_AT); \
 	fi
 endif   # EMBED_MANIFEST_AT
 endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 	touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
 endif
 endif	# WINNT && !GCC
 	chmod +x $@
@@ -810,17 +814,17 @@ crate_src_libdep = $(call mk_global_crat
 	$(REPORT_BUILD_VERBOSE)
 	$(ELOG) $(RCC) -name $* $< $(OUTOPTION)$@
 
 ifdef ASFILES
 # The AS_DASH_C_FLAG is needed cause not all assemblers (Solaris) accept
 # a '-c' flag.
 $(ASOBJS):
 	$(REPORT_BUILD_VERBOSE)
-	$(AS) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
+	"$(AS)" $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(_VPATH_SRCS)
 endif
 
 define syms_template
 syms:: $(2)
 $(2): $(1)
 	$$(call py_action,dumpsymbols,$$(abspath $$<) $$(abspath $$@))
 endef
 
@@ -1053,17 +1057,17 @@ force-cargo-host-program-check:
 	$(call CARGO_CHECK) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)
 else
 force-cargo-host-program-check:
 	@true
 endif # HOST_RUST_PROGRAMS
 
 $(SOBJS):
 	$(REPORT_BUILD)
-	$(AS) -o $@ $(DEFINES) $(ASFLAGS) $($(notdir $<)_FLAGS) $(LOCAL_INCLUDES) -c $<
+	"$(AS)" -o $@ $(DEFINES) $(ASFLAGS) $($(notdir $<)_FLAGS) $(LOCAL_INCLUDES) -c $<
 
 $(CPPOBJS):
 	$(REPORT_BUILD_VERBOSE)
 	$(call BUILDSTATUS,OBJECT_FILE $@)
 	$(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $(_VPATH_SRCS)
 
 $(CMMOBJS):
 	$(REPORT_BUILD_VERBOSE)
@@ -1102,17 +1106,17 @@ ifneq (,$(filter %.i,$(MAKECMDGOALS)))
 define PREPROCESS_RULES
 _PREPROCESSED_$1_FILES := $$(call _group_srcs,$1,$$($2))
 # Make preprocessed files PHONY so they are always executed, since they are
 # manual targets and we don't necessarily write to $@.
 .PHONY: $$(_PREPROCESSED_$1_FILES)
 
 # Hack up VPATH so we can reach the sources. Eg: 'make Parser.i' may need to
 # reach $(srcdir)/frontend/Parser.i
-vpath %.$1 $$(addprefix $$(srcdir)/,$$(sort $$(dir $$($2))))
+vpath %.$1 $$(addprefix $$(srcdir_rel)/,$$(sort $$(dir $$($2))))
 vpath %.$1 $$(addprefix $$(CURDIR)/,$$(sort $$(dir $$($2))))
 
 $$(_PREPROCESSED_$1_FILES): _DEPEND_CFLAGS=
 $$(_PREPROCESSED_$1_FILES): %.i: %.$1
 	$$(REPORT_BUILD_VERBOSE)
 	$$(addprefix $$(MKDIR) -p ,$$(filter-out .,$$(@D)))
 	$$($3) -C $$(PREPROCESS_OPTION)$$@ $(foreach var,$4,$$($(var))) $$($$(notdir $$<)_FLAGS) $$(_VPATH_SRCS)
 
@@ -1177,46 +1181,31 @@ endif
 endif
 
 $(RESFILE): %.res: %.rc
 	$(REPORT_BUILD)
 	@echo Creating Resource file: $@
 ifdef GNU_CC
 	$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $(_VPATH_SRCS)
 else
-	$(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $(_VPATH_SRCS)
+	$(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(INCLUDE_CFLAGS) $(OUTOPTION)$@ $(_VPATH_SRCS)
 endif
 
 # Cancel GNU make built-in implicit rules
 MAKEFLAGS += -r
 
 ifneq (,$(filter WINNT,$(OS_ARCH)))
 SEP := ;
 else
 SEP := :
 endif
 
 EMPTY :=
 SPACE := $(EMPTY) $(EMPTY)
 
-# MSYS has its own special path form, but javac expects the source and class
-# paths to be in the DOS form (i.e. e:/builds/...).  This function does the
-# appropriate conversion on Windows, but is a noop on other systems.
-ifeq ($(HOST_OS_ARCH),WINNT)
-#  We use 'pwd -W' to get DOS form of the path.  However, since the given path
-#  could be a file or a non-existent path, we cannot call 'pwd -W' directly
-#  on the path.  Instead, we extract the root path (i.e. "c:/"), call 'pwd -W'
-#  on it, then merge with the rest of the path.
-root-path = $(shell echo $(1) | sed -e 's|\(/[^/]*\)/\?\(.*\)|\1|')
-non-root-path = $(shell echo $(1) | sed -e 's|\(/[^/]*\)/\?\(.*\)|\2|')
-normalizepath = $(foreach p,$(1),$(if $(filter /%,$(1)),$(patsubst %/,%,$(shell cd $(call root-path,$(1)) && pwd -W))/$(call non-root-path,$(1)),$(1)))
-else
-normalizepath = $(1)
-endif
-
 ###############################################################################
 # Java rules
 ###############################################################################
 ifneq (,$(JAVAFILES)$(ANDROID_RESFILES)$(ANDROID_APKNAME)$(JAVA_JAR_TARGETS))
   include $(MOZILLA_DIR)/config/makefiles/java-build.mk
 endif
 
 ###############################################################################
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -634,25 +634,25 @@ case "$target" in
         HOST_CC='$(CC)'
         HOST_CXX='$(CXX)'
         AR='lib'
         AR_FLAGS='-NOLOGO -OUT:$@'
         AR_EXTRACT=
         RANLIB='echo not_ranlib'
         STRIP='echo not_strip'
         PKG_SKIP_STRIP=1
-        MKSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        MKCSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
+        MKSHLIB='"$(LINK)" -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
+        MKCSHLIB='"$(LINK)" -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         WIN32_SUBSYSTEM_VERSION=6.01
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
         _USE_CPP_INCLUDE_FLAG=1
-        _DEFINES_CFLAGS='-FI $(topobjdir)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
-        _DEFINES_CXXFLAGS='-FI $(topobjdir)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
+        _DEFINES_CFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
+        _DEFINES_CXXFLAGS='-FI $(DEPTH)/js/src/js-confdefs.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy -Zc:inline"
         CXXFLAGS="$CXXFLAGS -W3 -Gy -Zc:inline"
         if test "$CPU_ARCH" = "x86";then
           dnl VS2012+ defaults to -arch:SSE2. We want to target nothing
           dnl more recent, so set that explicitly here unless another
           dnl target arch has already been set.
           changequote(,)
           if test -z `echo $CFLAGS | grep -i [-/]arch:` ; then
@@ -887,17 +887,17 @@ fi
 AC_LANG_CPLUSPLUS
 
 MOZ_CXX11
 
 case "${OS_TARGET}" in
 WINNT|Darwin|Android)
   ;;
 *)
-  STL_FLAGS="-I${DIST}/stl_wrappers"
+  STL_FLAGS='-I$(DIST)/stl_wrappers'
   WRAP_STL_INCLUDES=1
   ;;
 esac
 
 dnl Checks for header files.
 dnl ========================================================
 AC_HEADER_DIRENT
 case "$target_os" in
--- a/old-configure.in
+++ b/old-configure.in
@@ -249,17 +249,17 @@ case "$target" in
             WRAP_STL_INCLUDES=1
             MOZ_MSVC_STL_WRAP_RAISE=1
             AC_DEFINE(MOZ_MSVC_STL_WRAP_RAISE)
         else
             AC_MSG_ERROR([Gecko exception wrapping doesn't understand your your MSVC/SDK.  Please file a bug describing this error and your build configuration.])
         fi
 
         if test "$WRAP_STL_INCLUDES" = "1"; then
-            STL_FLAGS="-I${DIST}/stl_wrappers"
+            STL_FLAGS='-I$(DIST)/stl_wrappers'
         fi
         CFLAGS="$CFLAGS -D_HAS_EXCEPTIONS=0"
         CXXFLAGS="$CXXFLAGS -D_HAS_EXCEPTIONS=0"
     else
         # Check w32api version
         _W32API_MAJOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $1 }'`
         _W32API_MINOR_VERSION=`echo $W32API_VERSION | $AWK -F\. '{ print $2 }'`
         AC_MSG_CHECKING([for w32api version >= $W32API_VERSION])
@@ -629,17 +629,17 @@ if test "$MOZ_DMD"; then
 fi
 
 dnl ========================================================
 dnl System overrides of the defaults for host
 dnl ========================================================
 case "$host" in
 *mingw*)
     if test -n "$_WIN32_MSVC"; then
-        HOST_AR=lib
+        HOST_AR=lib.exe
         HOST_AR_FLAGS='-NOLOGO -OUT:$@'
         HOST_CFLAGS="$HOST_CFLAGS -TC -nologo"
         HOST_RANLIB='echo ranlib'
     else
         HOST_CFLAGS="$HOST_CFLAGS -mwindows"
     fi
     HOST_CFLAGS="$HOST_CFLAGS -DXP_WIN32 -DXP_WIN -DWIN32 -D_WIN32 -D_CRT_SECURE_NO_WARNINGS"
     HOST_OPTIMIZE_FLAGS="${HOST_OPTIMIZE_FLAGS=-O2}"
@@ -830,31 +830,31 @@ case "$target" in
 
         # GCC/binutils can't link to a function if we try to include dllexport function
         # in the same library as dllimport caller. To work around it, we build NSPR
         # and NSS with -mnop-fun-dllimport flag. The drawback of this solution is that
         # function thunks need to be generated for cross-DLL calls.
         MOZ_FOLD_LIBS_FLAGS="-mnop-fun-dllimport"
     else
         TARGET_COMPILER_ABI=msvc
-        AR='lib'
+        AR='lib.exe'
         AR_FLAGS='-NOLOGO -OUT:$@'
         AR_EXTRACT=
         RANLIB='echo not_ranlib'
         STRIP='echo not_strip'
         PKG_SKIP_STRIP=1
-        MKSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
-        MKCSHLIB='$(LINK) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
+        MKSHLIB='"$(LINK)" -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
+        MKCSHLIB='"$(LINK)" -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
         WIN32_SUBSYSTEM_VERSION=6.01
         WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
         WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
         DSO_LDOPTS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
         _USE_CPP_INCLUDE_FLAG=1
-        _DEFINES_CFLAGS='-FI $(topobjdir)/mozilla-config.h -DMOZILLA_CLIENT'
-        _DEFINES_CXXFLAGS='-FI $(topobjdir)/mozilla-config.h -DMOZILLA_CLIENT'
+        _DEFINES_CFLAGS='-FI $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
+        _DEFINES_CXXFLAGS='-FI $(DEPTH)/mozilla-config.h -DMOZILLA_CLIENT'
         CFLAGS="$CFLAGS -W3 -Gy -Zc:inline"
         CXXFLAGS="$CXXFLAGS -W3 -Gy -Zc:inline"
         if test -z "$CLANG_CL"; then
             CPPFLAGS="$CPPFLAGS -utf-8"
         fi
         if test "$CPU_ARCH" = "x86"; then
             dnl VS2012+ defaults to -arch:SSE2. We want to target nothing
             dnl more recent, so set that explicitly here unless another
@@ -1856,17 +1856,17 @@ MOZ_ARG_WITH_BOOL(system-nss,
 
 if test -n "$_USE_SYSTEM_NSS"; then
     AM_PATH_NSS(3.33, [MOZ_SYSTEM_NSS=1], [AC_MSG_ERROR([you don't have NSS installed or your version is too old])])
 fi
 
 if test -n "$MOZ_SYSTEM_NSS"; then
    NSS_LIBS="$NSS_LIBS -lcrmf"
 else
-   NSS_CFLAGS="-I${DIST}/include/nss"
+   NSS_CFLAGS='-I$(DIST)/include/nss'
    case "${OS_ARCH}" in
         # Only few platforms have been tested with GYP
         WINNT|Darwin|Linux|DragonFly|FreeBSD|NetBSD|OpenBSD|SunOS)
             ;;
         *)
             AC_MSG_ERROR([building in-tree NSS is not supported on this platform. Use --with-system-nss])
             ;;
    esac
--- a/python/mozbuild/mozbuild/backend/base.py
+++ b/python/mozbuild/mozbuild/backend/base.py
@@ -251,16 +251,18 @@ class BuildBackend(LoggingMixin):
         pp = Preprocessor()
         srcdir = mozpath.dirname(obj.input_path)
         pp.context.update({
             k: ' '.join(v) if isinstance(v, list) else v
             for k, v in obj.config.substs.iteritems()
         })
         pp.context.update(
             top_srcdir=obj.topsrcdir,
+            top_srcdir_win=mozpath.win_path(obj.topsrcdir),
+            topsrcdir_rel=mozpath.relpath(obj.topsrcdir, mozpath.dirname(obj.output_path)),
             topobjdir=obj.topobjdir,
             srcdir=srcdir,
             relativesrcdir=mozpath.relpath(srcdir, obj.topsrcdir) or '.',
             DEPTH=mozpath.relpath(obj.topobjdir, mozpath.dirname(obj.output_path)) or '.',
         )
         pp.do_filter('attemptSubstitution')
         pp.setMarker(None)
         with self._write_file(obj.output_path) as fh:
--- a/python/mozbuild/mozbuild/backend/recursivemake.py
+++ b/python/mozbuild/mozbuild/backend/recursivemake.py
@@ -1195,19 +1195,21 @@ class RecursiveMakeBackend(CommonBackend
             # Ignore errors caused by the reftest module not being present.
             # This can happen when building SpiderMonkey standalone, for example.
             pass
 
     def _process_local_include(self, local_include, backend_file):
         d, path = self._pretty_path_parts(local_include, backend_file)
         if isinstance(local_include, ObjDirPath) and not d:
             # path doesn't start with a slash in this case
-            d = '$(CURDIR)/'
-        elif d == '$(DEPTH)':
-            d = '$(topobjdir)'
+            d = './'
+        elif d == '$(srcdir)':
+            d = '$(srcdir_rel)'
+        elif d == '$(topsrcdir)':
+            d = '$(topsrcdir_rel)'
         quoted_path = shell_quote(path) if path else path
         if quoted_path != path:
             path = quoted_path[0] + d + quoted_path[1:]
         else:
             path = d + path
         backend_file.write('LOCAL_INCLUDES += -I%s\n' % path)
 
     def _process_per_source_flag(self, per_source_flag, backend_file):
@@ -1247,17 +1249,17 @@ class RecursiveMakeBackend(CommonBackend
         backend_file.write_once('LIBRARY_NAME := %s\n' % libdef.basename)
         backend_file.write('FORCE_STATIC_LIB := 1\n')
         backend_file.write('REAL_LIBRARY := %s\n' % libdef.lib_name)
         if libdef.no_expand_lib:
             backend_file.write('NO_EXPAND_LIBS := 1\n')
 
     def _process_rust_library(self, libdef, backend_file):
         backend_file.write_once('%s := %s\n' % (libdef.LIB_FILE_VAR, libdef.import_name))
-        backend_file.write('CARGO_FILE := $(srcdir)/Cargo.toml\n')
+        backend_file.write('CARGO_FILE := $(srcdir_rel)/Cargo.toml\n')
         # Need to normalize the path so Cargo sees the same paths from all
         # possible invocations of Cargo with this CARGO_TARGET_DIR.  Otherwise,
         # Cargo's dependency calculations don't work as we expect and we wind
         # up recompiling lots of things.
         target_dir = mozpath.join(backend_file.objdir, libdef.target_dir)
         target_dir = mozpath.normpath(target_dir)
         backend_file.write('CARGO_TARGET_DIR := %s\n' % target_dir)
         if libdef.features:
@@ -1508,18 +1510,19 @@ class RecursiveMakeBackend(CommonBackend
             if extra:
                 pp.context.update(extra)
             if not pp.context.get('autoconfmk', ''):
                 pp.context['autoconfmk'] = 'autoconf.mk'
             pp.handleLine(b'# THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT MODIFY BY HAND.\n');
             pp.handleLine(b'DEPTH := @DEPTH@\n')
             pp.handleLine(b'topobjdir := @topobjdir@\n')
             pp.handleLine(b'topsrcdir := @top_srcdir@\n')
+            pp.handleLine(b'topsrcdir_rel := @topsrcdir_rel@\n')
             pp.handleLine(b'srcdir := @srcdir@\n')
-            pp.handleLine(b'VPATH := @srcdir@\n')
+            pp.handleLine(b'VPATH := @srcdir_rel@\n')
             pp.handleLine(b'relativesrcdir := @relativesrcdir@\n')
             pp.handleLine(b'include $(DEPTH)/config/@autoconfmk@\n')
             if not stub:
                 pp.do_include(obj.input_path)
             # Empty line to avoid failures when last line in Makefile.in ends
             # with a backslash.
             pp.handleLine(b'\n')
             pp.handleLine(b'include $(topsrcdir)/config/recurse.mk\n')
--- a/python/mozbuild/mozpack/path.py
+++ b/python/mozbuild/mozpack/path.py
@@ -1,33 +1,70 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import absolute_import
 
+from mozbuild.util import memoize
+import ntpath
+import platform
 import posixpath
 import os
 import re
 
 '''
 Like os.path, with a reduced set of functions, and with normalized path
 separators (always use forward slashes).
 Also contains a few additional utilities not found in os.path.
 '''
 
+@memoize
+def host_is_wsl():
+    return platform.system() == 'Linux' and 'Microsoft' in platform.uname()[2]
 
 def normsep(path):
     '''
     Normalize path separators, by using forward slashes instead of whatever
     os.sep is.
     '''
     return path.replace('\\', '/')
 
 
+if host_is_wsl():
+    def nativepath(path):
+        '''
+        Turn a Windows path into a Posix path in WSL.
+        '''
+        if ntpath.isabs(path):
+            drive, rest = ntpath.splitdrive(path)
+            if not drive:
+                # No drive letter, probably already a posix path.
+                return normsep(path)
+            return '/mnt/{}{}'.format(drive[0].lower(), normsep(rest))
+        else:
+            return normsep(path)
+
+    def win_path(path):
+        '''
+        Turn a Posix path into a Windows path in WSL.
+        '''
+        if path.startswith('/'):
+            if not path.startswith('/mnt'):
+                raise Exception("Can't convert a non-drvfs path to Windows format: %s" % path)
+            _, _, drive, rest = path.split('/', 3)
+            return drive + ':/' + rest
+        else:
+            return path
+else:
+    nativepath = normsep
+    def win_path(path):
+        return path
+
+
 def relpath(path, start):
     rel = normsep(os.path.relpath(path, start))
     return '' if rel == '.' else rel
 
 
 def realpath(path):
     return normsep(os.path.realpath(path))