Bug 1617794 - Wrap Windows tools with Wine on cross builds. r=dmajor
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 27 Feb 2020 04:42:57 +0000
changeset 515851 8cc7166e5113f81d878c7bd9cac2e74b324e2e6c
parent 515850 d407a28318e68dd78af8365a1ea3f8f7384f92c5
child 515852 509ec5e9380553a2bf20fbbdf49ba46b3502b3a3
push id108467
push usermh@glandium.org
push dateThu, 27 Feb 2020 04:45:01 +0000
treeherderautoland@1c707be763ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmajor
bugs1617794
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1617794 - Wrap Windows tools with Wine on cross builds. r=dmajor Windows programs run via Wine don't like Unix absolute paths (they look like command line arguments), so we need to use relative paths. Mingw already run fxc2 via wine, but for some reason it doesn't care about the Unix absolute paths. genshaders does need some adjustements to run properly with the real fxc. Now, on actual Windows, because the temporary directory where tempfile.NamedTemporaryFile creates files by default is not necessarily on the same drive as where the command runs from, a relative path can't be constructed. So we also force the temporary file to be created in the current (obj) directory. There is no similar concern for other files because we only go from objdir to srcdir, and the build system already doesn't support both being on a separate drive. While here, flush stdout when the genshared script writes to it, so that the messages are printed out immediately rather than randomly, later, after output from subprocesses. Differential Revision: https://phabricator.services.mozilla.com/D64294
accessible/interfaces/gecko/Makefile.in
accessible/interfaces/ia2/Makefile.in
accessible/interfaces/msaa/Makefile.in
accessible/ipc/win/handler/Makefile.in
accessible/ipc/win/typelib/Makefile.in
config/rules.mk
gfx/layers/d3d11/genshaders.py
moz.configure
python/mozbuild/mozbuild/action/exe_7z_archive.py
toolkit/crashreporter/tools/symbolstore.py
toolkit/moz.configure
toolkit/mozapps/installer/windows/nsis/makensis.mk
--- a/accessible/interfaces/gecko/Makefile.in
+++ b/accessible/interfaces/gecko/Makefile.in
@@ -12,17 +12,17 @@ MIDL_GENERATED_FILES = \
   IGeckoCustom.tlb \
   $(NULL)
 
 # Bug 1420119: We need the trailing semicolon here to generate a recipe for the
 # midl targets to avoid timestamp caching issues.
 $(MIDL_GENERATED_FILES): done_gen ;
 
 done_gen: $(srcdir)/IGeckoCustom.idl
-	$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -Oicf $(srcdir)/IGeckoCustom.idl
+	$(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) -I $(srcdir_rel) -Oicf $(srcdir_rel)/IGeckoCustom.idl
 	touch $@
 
 export:: done_gen
 
 midl_exports := \
     IGeckoCustom.h \
     IGeckoCustom_i.c \
     $(NULL)
--- a/accessible/interfaces/ia2/Makefile.in
+++ b/accessible/interfaces/ia2/Makefile.in
@@ -1,13 +1,13 @@
 # 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/.
 
-IA2DIR        = $(topsrcdir)/other-licenses/ia2
+IA2DIR        = $(srcdir_rel)/$(DEPTH)/other-licenses/ia2
 
 GARBAGE       += $(MIDL_GENERATED_FILES) \
                  $(MIDL_UNUSED_GENERATED_FILES) \
                  midl_done \
                  typelib_done \
                  $(NULL)
 
 # Please keep this list in sync with the moz.build file until the rest of this
@@ -87,23 +87,23 @@ missing_base:=$(sort $(basename $(subst 
 $(MIDL_GENERATED_FILES) : midl_done typelib_done ;
 
 ifneq ("$(missing)","")
 midl_done : FORCE
 endif
 
 midl_done : $(addprefix $(IA2DIR)/,$(MIDL_INTERFACES) $(MIDL_ENUMS))
 	for idl in $(sort $(subst FORCE,,$?) $(addsuffix .idl,$(addprefix $(IA2DIR)/,$(missing_base)))); do \
-	  $(MIDL) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -Oicf $$idl; \
+	  $(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -Oicf $$idl; \
 	done
 	touch $@
 
 # The intent of this rule is to generate the .tlb file that is referenced in the
 # .rc file for IA2Marshal.dll
-typelib_done : $(addprefix $(srcdir)/,$(MIDL_LIBRARIES))
+typelib_done : $(addprefix $(srcdir_rel)/,$(MIDL_LIBRARIES))
 	for idl in $?; do \
-	  $(MIDL) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -D _MIDL_DECLARE_WIREM_HANDLE -dlldata `basename $$idl .idl`.c -Oicf $$idl; \
+	  $(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) -app_config -I $(IA2DIR) -D _MIDL_DECLARE_WIREM_HANDLE -dlldata `basename $$idl .idl`.c -Oicf $$idl; \
 	done
 	touch $@
 
 # This marshall dll is NOT registered in the installer (agreed to by IA2 participants)
 register::
 	regsvr32 -s $(DIST)/bin/$(SHARED_LIBRARY)
--- a/accessible/interfaces/msaa/Makefile.in
+++ b/accessible/interfaces/msaa/Makefile.in
@@ -15,18 +15,17 @@ MIDL_GENERATED_FILES = \
 # Bug 1420119: We need the trailing semicolon here to generate a recipe for the
 # midl targets to avoid timestamp caching issues.
 $(MIDL_GENERATED_FILES): done_gen ;
 
 done_gen: $(srcdir)/ISimpleDOM.idl \
           $(srcdir)/ISimpleDOMNode.idl \
           $(srcdir)/ISimpleDOMDocument.idl \
           $(srcdir)/ISimpleDOMText.idl
-
-	$(MIDL) $(MIDL_FLAGS) -I $(srcdir) -robust -Oicf $(srcdir)/ISimpleDOM.idl
+	$(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) -I $(srcdir_rel) -robust -Oicf $(srcdir_rel)/ISimpleDOM.idl
 	touch $@
 
 export:: done_gen
 
 # This marshall dll is also registered in the installer
 register::
 	regsvr32 -s $(DIST)/bin/$(SHARED_LIBRARY)
 
--- a/accessible/ipc/win/handler/Makefile.in
+++ b/accessible/ipc/win/handler/Makefile.in
@@ -1,14 +1,14 @@
 # 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/.
 
-IA2DIR = $(topsrcdir)/other-licenses/ia2
-MSAADIR = $(topsrcdir)/accessible/interfaces/msaa
+IA2DIR = $(srcdir_rel)/$(DEPTH)/other-licenses/ia2
+MSAADIR = $(srcdir_rel)/$(DEPTH)/accessible/interfaces/msaa
 GARBAGE += $(MIDL_GENERATED_FILES) midl_done
 
 MIDL_GENERATED_FILES = \
   dlldata.c \
   HandlerData.h \
   HandlerData_c.c \
   HandlerData_i.c \
   HandlerData_p.c \
@@ -17,17 +17,17 @@ MIDL_GENERATED_FILES = \
 
 export:: $(MIDL_GENERATED_FILES)
 
 # Bug 1420119: We need the trailing semicolon here to generate a recipe for the
 # midl targets to avoid timestamp caching issues.
 $(MIDL_GENERATED_FILES): midl_done ;
 
 midl_done: $(srcdir)/HandlerData.acf $(srcdir)/HandlerData.idl
-	$(MIDL) $(MIDL_FLAGS) $(DEFINES) -I $(topobjdir) -I $(DIST)/include -I $(IA2DIR) -I $(MSAADIR) -Oicf -acf $(srcdir)/HandlerData.acf $(srcdir)/HandlerData.idl
+	$(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) $(DEFINES) -I $(DEPTH) -I $(DEPTH)/dist/include -I $(IA2DIR) -I $(MSAADIR) -Oicf -acf $(srcdir_rel)/HandlerData.acf $(srcdir_rel)/HandlerData.idl
 	touch $@
 
 INSTALL_TARGETS += midl
 midl_FILES := HandlerData.h \
               HandlerData_i.c \
               $(NULL)
 midl_DEST := $(DIST)/include
 midl_TARGET := midl
--- a/accessible/ipc/win/typelib/Makefile.in
+++ b/accessible/ipc/win/typelib/Makefile.in
@@ -11,17 +11,17 @@ MIDL_GENERATED_FILES = \
   Accessible.tlb \
   $(NULL)
 
 # Bug 1420119: We need the trailing semicolon here to generate a recipe for the
 # midl targets to avoid timestamp caching issues.
 $(MIDL_GENERATED_FILES): done_gen ;
 
 done_gen: $(srcdir)/Accessible.idl
-	$(MIDL) $(MIDL_FLAGS) -Oicf $(srcdir)/Accessible.idl
+	$(call WINEWRAP,$(MIDL)) $(MIDL_FLAGS) -Oicf $(srcdir_rel)/Accessible.idl
 	touch $@
 
 export:: done_gen
 
 midl_exports := \
   Accessible.tlb \
   $(NULL)
 
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -671,22 +671,36 @@ crate_src_libdep = $(call mk_global_crat
 $(COBJS):
 	$(REPORT_BUILD_VERBOSE)
 	$(CC) $(OUTOPTION)$@ -c $(COMPILE_CFLAGS) $($(notdir $<)_FLAGS) $<
 
 $(CWASMOBJS):
 	$(REPORT_BUILD_VERBOSE)
 	$(WASM_CC) $(OUTOPTION)$@ -c $(WASM_CFLAGS) $($(notdir $<)_FLAGS) $<
 
+WINEWRAP = $(if $(and $(filter %.exe,$1),$(WINE)),$(WINE) $1,$1)
+
+# Windows program run via Wine don't like Unix absolute paths (they look
+# like command line arguments). So when needed, create relative paths
+# from absolute paths. We start with $(DEPTH), which gets us to topobjdir,
+# then add "/.." for each component of topobjdir, which gets us to /.
+# then we can add the absolute path after that and we have a relative path,
+# albeit longer than it could be.
+ifdef WINE
+relativize = $(if $(filter /%,$1),$(DEPTH)$(subst $(space),,$(foreach d,$(subst /, ,$(topobjdir)),/..))$1,$1)
+else
+relativize = $1
+endif
+
 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) $<
+	$(call WINEWRAP,$(AS)) $(ASOUTOPTION)$@ $(ASFLAGS) $($(notdir $<)_FLAGS) $(AS_DASH_C_FLAG) $(call relativize,$<)
 endif
 
 define syms_template
 syms:: $(2)
 $(2): $(1)
 ifdef MOZ_CRASHREPORTER
 	$$(call py_action,dumpsymbols,$$(abspath $$<) $$(abspath $$@) $$(DUMP_SYMBOLS_FLAGS))
 endif
@@ -720,17 +734,17 @@ else ifdef MOZ_CRASHREPORTER
 endif
 
 ifneq (,$(RUST_TESTS)$(RUST_LIBRARY_FILE)$(HOST_RUST_LIBRARY_FILE)$(RUST_PROGRAMS)$(HOST_RUST_PROGRAMS))
 include $(MOZILLA_DIR)/config/makefiles/rust.mk
 endif
 
 $(SOBJS):
 	$(REPORT_BUILD)
-	$(AS) $(ASOUTOPTION)$@ $(SFLAGS) $($(notdir $<)_FLAGS) -c $<
+	$(call WINEWRAP,$(AS)) $(ASOUTOPTION)$@ $(SFLAGS) $($(notdir $<)_FLAGS) -c $(call relativize,$<)
 
 $(CPPOBJS):
 	$(REPORT_BUILD_VERBOSE)
 	$(call BUILDSTATUS,OBJECT_FILE $@)
 	$(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS) $($(notdir $<)_FLAGS) $<
 
 $(CPPWASMOBJS):
 	$(REPORT_BUILD_VERBOSE)
@@ -849,17 +863,17 @@ endif
 endif
 
 $(RESFILE): %.res: $(RCFILE)
 	$(REPORT_BUILD)
 	@echo Creating Resource file: $@
 ifdef GNU_CC
 	$(RC) $(RCFLAGS) $(filter-out -U%,$(DEFINES)) $(INCLUDES:-I%=--include-dir %) $(OUTOPTION)$@ $<
 else
-	$(RC) $(RCFLAGS) -r $(DEFINES) $(INCLUDES) $(OUTOPTION)$@ $<
+	$(call WINEWRAP,$(RC)) $(RCFLAGS) -r $(DEFINES) $(INCLUDES:-I%=-I$(call relativize,%)) $(OUTOPTION)$@ $(call relativize,$<)
 endif
 
 # Cancel GNU make built-in implicit rules
 MAKEFLAGS += -r
 
 ifneq (,$(filter WINNT,$(OS_ARCH)))
 SEP := ;
 else
--- a/gfx/layers/d3d11/genshaders.py
+++ b/gfx/layers/d3d11/genshaders.py
@@ -78,33 +78,34 @@ def run_fxc(shader_model,
             shader_name,
             output_fp):
     fxc_location = buildconfig.substs['FXC']
 
     argv = [
         fxc_location,
         '-nologo',
         '-T{0}'.format(shader_model),
-        shader_file,
+        os.path.relpath(shader_file),
         '-E{0}'.format(shader_name),
         '-Vn{0}'.format(shader_name),
         '-Vi',
     ]
     if 'Linux' in buildconfig.substs['HOST_OS_ARCH']:
         argv.insert(0, buildconfig.substs['WINE'])
     if shader_model.startswith('vs_'):
         argv += ['-DVERTEX_SHADER']
     elif shader_model.startswith('ps_'):
         argv += ['-DPIXEL_SHADER']
 
     deps = None
     with ScopedTempFilename() as temp_filename:
-        argv += ['-Fh{0}'.format(temp_filename)]
+        argv += ['-Fh{0}'.format(os.path.relpath(temp_filename))]
 
         sys.stdout.write('{0}\n'.format(' '.join(argv)))
+        sys.stdout.flush()
         proc_stdout = subprocess.check_output(argv)
         proc_stdout = decode_console_text(sys.stdout, proc_stdout)
         deps = find_dependencies(proc_stdout)
         assert 'fxc2' in fxc_location or len(deps) > 0
 
         with open(temp_filename, 'r') as temp_fp:
             output_fp.write(temp_fp.read())
 
@@ -122,16 +123,20 @@ def find_dependencies(fxc_output):
     # brackets. We filter out potentially bogus strings later.
     deps = set()
     for line in fxc_output.split('\n'):
         m = re.search(r"\[([^\]]+)\]", line)
         if m is None:
             continue
         dep_path = m.group(1)
         dep_path = os.path.normpath(dep_path)
+        # When run via Wine, FXC's output contains Windows paths on the Z drive.
+        # We want to normalize them back to unix paths for the build system.
+        if 'Linux' in buildconfig.substs['HOST_OS_ARCH'] and dep_path.lower().startswith('z:'):
+            dep_path = dep_path[2:].replace('\\', '/')
         if os.path.isfile(dep_path):
             deps.add(dep_path)
     return deps
 
 # Python reads the raw bytes from stdout, so we need to try our best to
 # capture that as a valid Python string.
 
 
@@ -150,17 +155,17 @@ def decode_console_text(pipe, text):
 # wrapper for this since TemporaryNamedFile holds the file open.
 
 
 class ScopedTempFilename(object):
     def __init__(self):
         self.name = None
 
     def __enter__(self):
-        with tempfile.NamedTemporaryFile(delete=False) as tmp:
+        with tempfile.NamedTemporaryFile(dir=os.getcwd(), delete=False) as tmp:
             self.name = tmp.name
             return self.name
 
     def __exit__(self, type, value, traceback):
         if not self.name:
             return
         try:
             os.unlink(self.name)
--- a/moz.configure
+++ b/moz.configure
@@ -531,16 +531,21 @@ check_prog('DSYMUTIL', extra_programs.DS
            allow_missing=True)
 check_prog('MKFSHFS', extra_programs.MKFSHFS,
            allow_missing=True)
 check_prog('HFS_TOOL', extra_programs.HFS_TOOL,
            allow_missing=True)
 check_prog('RPMBUILD', extra_programs.RPMBUILD,
            allow_missing=True)
 
+wine = check_prog(
+    'WINE', ['wine'], allow_missing=True,
+    when=depends(target, host, compile_environment)(
+        lambda t, h, c: c and t.kernel == 'WINNT' and h.kernel == 'Linux'))
+
 
 @depends(target)
 @imports('os')
 def makensis_progs(target):
     if target.kernel != 'WINNT':
         return
 
     candidates = [
@@ -557,23 +562,29 @@ def makensis_progs(target):
         prefix = os.path.dirname(os.environ['MSYSTEM_PREFIX'])
         candidates.insert(0, os.path.join(prefix, 'mingw32', 'bin', 'makensis.exe'))
 
     return tuple(candidates)
 
 nsis = check_prog('MAKENSISU', makensis_progs, allow_missing=True)
 
 # Make sure the version of makensis is up to date.
-@depends_if(nsis)
+@depends(nsis, wine)
 @checking('for NSIS version')
 @imports('re')
-def nsis_version(nsis):
+def nsis_version(nsis, wine):
+    if not nsis:
+        return None
     nsis_min_version = '3.0b1'
-    out = check_cmd_output(nsis, '-version',
-                           onerror=lambda: die('Failed to get nsis version.'))
+    onerror = lambda: die('Failed to get nsis version.')
+    if wine and nsis.lower().endswith('.exe'):
+        out = check_cmd_output(wine, nsis, '-version', onerror=onerror)
+    else:
+        out = check_cmd_output(nsis, '-version', onerror=onerror)
+
     m = re.search(r'(?<=v)[0-9]+\.[0-9]+((a|b|rc)[0-9]+)?', out)
 
     if not m:
         raise FatalCheckError('Unknown version of makensis')
     ver = Version(m.group(0))
 
     # Versions comparisons don't quite work well with beta versions, so ensure
     # it works for the non-beta version.
--- a/python/mozbuild/mozbuild/action/exe_7z_archive.py
+++ b/python/mozbuild/mozbuild/action/exe_7z_archive.py
@@ -17,18 +17,23 @@ from mozbuild.base import BuildEnvironme
 def archive_exe(pkg_dir, tagfile, sfx_package, package, use_upx):
     tmpdir = tempfile.mkdtemp(prefix='tmp')
     try:
         if pkg_dir:
             shutil.move(pkg_dir, 'core')
 
         if use_upx:
             final_sfx = mozpath.join(tmpdir, '7zSD.sfx')
-            subprocess.check_call([
-                buildconfig.substs.get('UPX', 'upx'),
+            upx = buildconfig.substs.get('UPX', 'upx')
+            wine = buildconfig.substs.get('WINE')
+            if wine and upx.lower().endswith('.exe'):
+                cmd = [wine, upx]
+            else:
+                cmd = [upx]
+            subprocess.check_call(cmd + [
                 '--best',
                 '-o',
                 final_sfx,
                 sfx_package,
             ])
         else:
             final_sfx = sfx_package
 
--- a/toolkit/crashreporter/tools/symbolstore.py
+++ b/toolkit/crashreporter/tools/symbolstore.py
@@ -680,21 +680,24 @@ class Dumper_Win32(Dumper):
 
 
     def CopyDebug(self, file, debug_file, guid, code_file, code_id):
         file = locate_pdb(file)
         def compress(path):
             compressed_file = path[:-1] + '_'
             # ignore makecab's output
             makecab = buildconfig.substs['MAKECAB']
-            success = subprocess.call([makecab, "-D",
-                                       "CompressionType=MSZIP",
-                                       path, compressed_file],
-                                      stdout=open(os.devnull, 'w'),
-                                      stderr=subprocess.STDOUT)
+            wine = buildconfig.substs.get('WINE')
+            if wine and makecab.lower().endswith('.exe'):
+                cmd = [wine, makecab]
+            else:
+                cmd = [makecab]
+            success = subprocess.call(
+                cmd + ["-D", "CompressionType=MSZIP", path, compressed_file],
+                stdout=open(os.devnull, 'w'), stderr=subprocess.STDOUT)
             if success == 0 and os.path.exists(compressed_file):
                 os.unlink(path)
                 return True
             return False
 
         rel_path = os.path.join(debug_file,
                                 guid,
                                 debug_file).replace("\\", "/")
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -1148,29 +1148,41 @@ def check_for_midl(target, compile_envir
     if compile_environment:
         return True
 
 
 midl = check_prog('MIDL', midl_names, when=check_for_midl, allow_missing=True,
                   paths=sdk_bin_path)
 
 
-@depends(c_compiler, target,
+@depends(c_compiler, target, host,
          when=depends(midl, target)(lambda m, t: m and t.kernel == 'WINNT'))
 @imports(_from='mozbuild.shellutil', _import='quote')
-def midl_flags(c_compiler, target):
+def midl_flags(c_compiler, target, host):
     if c_compiler and c_compiler.type == 'clang-cl':
         env = {
             'x86': 'win32',
             'x86_64': 'x64',
             'aarch64': 'arm64',
         }[target.cpu]
         flags = ['-env', env]
 
-        return flags + ['-cpp_cmd', c_compiler.compiler]
+        if host.os == 'WINNT':
+            return flags + ['-cpp_cmd', c_compiler.compiler]
+        else:
+            # If cross-compiling, for now, we'll assume we can find the
+            # Windows version of clang-cl in the PATH. It is required because
+            # while Wine is able to spawn Linux processes from Windows
+            # programs(!), the calling program doesn't have access to the process
+            # output and can't wait for it to finish. Midl runs clang-cl as
+            # a preprocessor and expects to read its output...
+            clang_cl_exe = find_program('clang-cl.exe')
+            if not clang_cl_exe:
+                die("Cannot find clang-cl.exe")
+            return flags + ['-cpp_cmd', clang_cl_exe]
 
     # mingw
     return {
         'x86': ['--win32', '-m32'],
         'x86_64': ['--win64', '-m64'],
     }[target.cpu]
 
 
@@ -1388,18 +1400,16 @@ set_config('MOZ_LAYOUT_DEBUGGER', depend
 
 # Shader Compiler for Windows (and MinGW Cross Compile)
 # ==============================================================
 
 with only_when(compile_environment):
     fxc = check_prog('FXC', ('fxc.exe', 'fxc2.exe'), when=depends(target)
                      (lambda t: t.kernel == 'WINNT'),
                      paths=sdk_bin_path)
-    wine = check_prog('WINE', ['wine'], when=depends(target, host)
-                      (lambda t, h: t.kernel == 'WINNT' and h.kernel == 'Linux'))
 
 
 # VPX
 # ===
 
 with only_when(compile_environment):
     option('--with-system-libvpx',
            help='Use system libvpx (located with pkgconfig)')
--- a/toolkit/mozapps/installer/windows/nsis/makensis.mk
+++ b/toolkit/mozapps/installer/windows/nsis/makensis.mk
@@ -48,19 +48,19 @@ CUSTOM_NSIS_PLUGINS = \
 CUSTOM_UI = \
 	nsisui.exe \
 	$(NULL)
 
 $(CONFIG_DIR)/setup.exe::
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/,$(TOOLKIT_NSIS_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/Plugins/,$(CUSTOM_NSIS_PLUGINS)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/,$(CUSTOM_UI)) $(CONFIG_DIR)
-	cd $(CONFIG_DIR) && $(MAKENSISU) $(MAKENSISU_FLAGS) installer.nsi
+	cd $(CONFIG_DIR) && $(call WINEWRAP,$(MAKENSISU)) $(MAKENSISU_FLAGS) installer.nsi
 ifdef MOZ_STUB_INSTALLER
-	cd $(CONFIG_DIR) && $(MAKENSISU) $(MAKENSISU_FLAGS) stub.nsi
+	cd $(CONFIG_DIR) && $(call WINEWRAP,$(MAKENSISU)) $(MAKENSISU_FLAGS) stub.nsi
 endif
 
 ifdef ZIP_IN
 installer:: $(CONFIG_DIR)/setup.exe $(ZIP_IN)
 	@echo 'Packaging $(WIN32_INSTALLER_OUT).'
 	$(NSINSTALL) -D '$(ABS_DIST)/$(PKG_INST_PATH)'
 	$(MOZILLA_DIR)/mach repackage installer \
 	  -o '$(ABS_DIST)/$(PKG_INST_PATH)$(PKG_INST_BASENAME).exe' \
@@ -100,17 +100,17 @@ HELPER_DEPS = $(GLOBAL_DEPS) \
 	$(INSTALL) $(addprefix $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/,$(BRANDING_FILES)) $(CONFIG_DIR)
 	$(call py_action,preprocessor,-Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in -o $(CONFIG_DIR)/defines.nsi)
 	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
 	  --preprocess-locale $(topsrcdir) \
 	  $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/,$(TOOLKIT_NSIS_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/Plugins/,$(CUSTOM_NSIS_PLUGINS)) $(CONFIG_DIR)
-	cd $(CONFIG_DIR) && $(MAKENSISU) $(MAKENSISU_FLAGS) uninstaller.nsi
+	cd $(CONFIG_DIR) && $(call WINEWRAP,$(MAKENSISU)) $(MAKENSISU_FLAGS) uninstaller.nsi
 
 uninstaller:: $(CONFIG_DIR)/helper.exe
 	$(NSINSTALL) -D $(DIST)/bin/uninstall
 	cp $(CONFIG_DIR)/helper.exe $(DIST)/bin/uninstall
 
 ifdef MOZ_MAINTENANCE_SERVICE
 maintenanceservice_installer::
 	$(RM) -r $(CONFIG_DIR)
@@ -119,12 +119,12 @@ maintenanceservice_installer::
 	$(INSTALL) $(addprefix $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/,$(BRANDING_FILES)) $(CONFIG_DIR)
 	$(call py_action,preprocessor,-Fsubstitution $(DEFINES) $(ACDEFINES) \
 	  $(srcdir)/nsis/defines.nsi.in -o $(CONFIG_DIR)/defines.nsi)
 	$(PYTHON) $(topsrcdir)/toolkit/mozapps/installer/windows/nsis/preprocess-locale.py \
 	  --preprocess-locale $(topsrcdir) \
 	  $(PPL_LOCALE_ARGS) $(AB_CD) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/toolkit/mozapps/installer/windows/nsis/,$(TOOLKIT_NSIS_FILES)) $(CONFIG_DIR)
 	$(INSTALL) $(addprefix $(MOZILLA_DIR)/other-licenses/nsis/Plugins/,$(CUSTOM_NSIS_PLUGINS)) $(CONFIG_DIR)
-	cd $(CONFIG_DIR) && $(MAKENSISU) $(MAKENSISU_FLAGS) maintenanceservice_installer.nsi
+	cd $(CONFIG_DIR) && $(call WINEWRAP,$(MAKENSISU)) $(MAKENSISU_FLAGS) maintenanceservice_installer.nsi
 	$(NSINSTALL) -D $(DIST)/bin/
 	cp $(CONFIG_DIR)/maintenanceservice_installer.exe $(DIST)/bin
 endif