Bug 1656141 - Stop using MT to insert manifests in binaries. r=firefox-build-system-reviewers,rstewart

We are currently relying on two different ways to insert side-by-side
manifests in binaries on Windows: through resource files, or through
the use of MT. The latter is not supported on mingw builds, which is
not great.

Link.exe has options to add a manifest at link time without relying on
either method above, but that's not supported on mingw either.

So the best we can do is to move everything to using resource files.
This also avoids using MT, which, on cross builds, requires using wine.

Ideally, the manifests would be declared in moz.build, but that
complicates things for cases like TestDllInterceptor, where there are
multiple binaries in the same directory, but only one of them needs the
manifest. This keeps the status quo of getting the manifest
automatically from the source directory.

Differential Revision: https://phabricator.services.mozilla.com/D85382
This commit is contained in:
Mike Hommey 2020-08-06 16:00:40 +00:00
parent b8f0039ca8
commit dc4ee999b0
3 changed files with 34 additions and 56 deletions

View File

@ -457,30 +457,6 @@ def sdk_bin_path(valid_windows_sdk_dir, valid_ucrt_sdk_dir, host):
return result
# allow_missing=True for mingw builds, until bug 1617793
mt = check_prog('MT', ('mt.exe',), allow_missing=True, paths=sdk_bin_path)
# Check that MT is not something unexpected like "magnetic tape manipulation
# utility".
@depends(mt, wine)
@checking('whether MT is really Microsoft Manifest Tool', lambda x: bool(x))
def valid_mt(path, wine):
if not path:
return None
if wine and path.lower().endswith('.exe'):
out = check_cmd_output(wine, path, onerror=lambda: '').splitlines()
else:
out = check_cmd_output(path, onerror=lambda: '').splitlines()
out = '\n'.join(l for l in out
if 'Microsoft (R) Manifest Tool' in l)
if out:
return path
raise FatalCheckError('%s is not Microsoft Manifest Tool')
set_config('MSMANIFEST_TOOL', depends(valid_mt)(lambda x: bool(x)))
js_option(env='LINKER', nargs=1, when=target_is_windows, help='Path to the linker')
link = check_prog('LINKER', ('lld-link',), input='LINKER',

View File

@ -111,6 +111,17 @@ def split_and_normalize_version(version, len):
return ([digits_only(x) for x in version.split('.')] + ['0'] * len)[:len]
def has_manifest(module_rc, manifest_id):
for line in module_rc.splitlines():
line = line.split(None, 2)
if len(line) < 2:
continue
id, what, *rest = line
if id == manifest_id and what in ('24', 'RT_MANIFEST'):
return True
return False
def generate_module_rc(binary='', rcinclude=None):
deps = set()
buildid = get_buildid()
@ -170,6 +181,13 @@ def generate_module_rc(binary='', rcinclude=None):
productname=overrides.get('WIN32_MODULE_PRODUCTNAME', display_name),
buildid=buildid,
)
manifest_id = '2' if binary.lower().endswith('.dll') else '1'
if binary and not has_manifest(data, manifest_id):
manifest_path = os.path.join(srcdir, binary + '.manifest')
if os.path.exists(manifest_path):
data += '\n{} RT_MANIFEST "{}"\n'.format(manifest_id, manifest_path)
with io.open('{}.rc'.format(binary or 'module'), 'w', encoding='latin1') as fh:
fh.write(data)

View File

@ -400,9 +400,14 @@ everything::
GLOBAL_DEPS += Makefile $(addprefix $(DEPTH)/config/,$(INCLUDED_AUTOCONF_MK)) $(MOZILLA_DIR)/config/config.mk
ifeq ($(OS_ARCH),WINNT)
# We always build .res files for programs and shared libraries
resfile = $(notdir $1).res
# We also build .res files for simple programs if a corresponding manifest
# exists. We'll generate a .rc file that includes the manifest.
resfile_for_manifest = $(if $(wildcard $(srcdir)/$(notdir $1).manifest),$(call resfile,$1))
else
resfile =
resfile_for_manifest =
endif
##############################################
@ -456,18 +461,8 @@ endef
#
$(PROGRAM): $(PROGOBJS) $(STATIC_LIBS) $(EXTRA_DEPS) $(call resfile,$(PROGRAM)) $(GLOBAL_DEPS) $(call mkdir_deps,$(FINAL_TARGET))
$(REPORT_BUILD)
@$(RM) $@.manifest
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
$(LINKER) -OUT:$@ -PDB:$(LINK_PDBFILE) -IMPLIB:$(basename $(@F)).lib $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $($(notdir $@)_OBJS) $(filter %.res,$^) $(STATIC_LIBS) $(SHARED_LIBS) $(OS_LIBS)
ifdef MSMANIFEST_TOOL
@if test -f $@.manifest; then \
echo "Manifest in objdir is not supported"; \
exit 1; \
elif test -f '$(srcdir)/$(notdir $@).manifest'; then \
echo 'Embedding manifest from $(srcdir_rel)/$(notdir $@).manifest'; \
$(call WINEWRAP,$(MT)) -NOLOGO -MANIFEST '$(srcdir_rel)/$(notdir $@).manifest' -OUTPUTRESOURCE:$@\;1; \
fi
endif # MSVC with manifest tool
else # !WINNT || GNU_CC
$(call EXPAND_CC_OR_CXX,$@) -o $@ $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) $($(notdir $@)_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
$(call py_action,check_binary,--target $@)
@ -503,20 +498,17 @@ endif
# SIMPLE_PROGRAMS = Foo Bar
# creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
#
$(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(STATIC_LIBS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
define simple_program_deps
$1: $(1:$(BIN_SUFFIX)=.$(OBJ_SUFFIX)) $(STATIC_LIBS) $(EXTRA_DEPS) $(call resfile_for_manifest,$1) $(GLOBAL_DEPS)
endef
$(foreach p,$(SIMPLE_PROGRAMS),$(eval $(call simple_program_deps,$(p))))
$(SIMPLE_PROGRAMS):
$(REPORT_BUILD)
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
$(LINKER) -out:$@ -pdb:$(LINK_PDBFILE) $($@_OBJS) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(OS_LIBS)
ifdef MSMANIFEST_TOOL
@if test -f $@.manifest; then \
echo "Manifest in objdir is not supported"; \
exit 1; \
elif test -f '$(srcdir)/$(notdir $@).manifest'; then \
$(call WINEWRAP,$(MT)) -NOLOGO -MANIFEST '$(srcdir_rel)/$(notdir $@).manifest' -OUTPUTRESOURCE:$@\;1; \
fi
endif # MSVC with manifest tool
$(LINKER) -out:$@ -pdb:$(LINK_PDBFILE) $($@_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(OS_LIBS)
else
$(call EXPAND_CC_OR_CXX,$@) $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) -o $@ $($@_OBJS) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
$(call EXPAND_CC_OR_CXX,$@) $(COMPUTED_CXX_LDFLAGS) $(PGO_CFLAGS) -o $@ $($@_OBJS) $(filter %.res,$^) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(OS_LIBS)
$(call py_action,check_binary,--target $@)
endif # WINNT && !GNU_CC
@ -600,15 +592,6 @@ endif
$(call py_action,check_binary,--target $@)
ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
ifdef MSMANIFEST_TOOL
@if test -f $@.manifest; then \
echo "Manifest in objdir is not supported"; \
exit 1; \
elif test -f '$(srcdir)/$@.manifest'; then \
echo 'Embedding manifest from $(srcdir_rel)/$@.manifest'; \
$(call WINEWRAP,$(MT)) -NOLOGO -MANIFEST '$(srcdir_rel)/$@.manifest' -OUTPUTRESOURCE:$@\;2; \
fi
endif # MSVC with manifest tool
endif # WINNT && !GCC
chmod +x $@
ifdef ENABLE_STRIP
@ -852,7 +835,8 @@ endif
endif
%.res: $(or $(RCFILE),%.rc)
# EXTRA_DEPS contains manifests (manually added in Makefile.in ; bug 1498414)
%.res: $(or $(RCFILE),%.rc) $(EXTRA_DEPS)
$(REPORT_BUILD)
@echo Creating Resource file: $@
ifdef GNU_CC
@ -861,7 +845,7 @@ else
$(call WINEWRAP,$(RC)) $(RCFLAGS) -r $(DEFINES) $(INCLUDES:-I%=-I$(call relativize,%)) $(OUTOPTION)$@ $(call relativize,$<)
endif
$(notdir $(addsuffix .rc,$(PROGRAM) $(SHARED_LIBRARY) module)): %.rc: $(RCINCLUDE) $(MOZILLA_DIR)/config/create_rc.py
$(notdir $(addsuffix .rc,$(PROGRAM) $(SHARED_LIBRARY) $(SIMPLE_PROGRAMS) module)): %.rc: $(RCINCLUDE) $(MOZILLA_DIR)/config/create_rc.py
$(PYTHON3) $(MOZILLA_DIR)/config/create_rc.py '$(if $(filter module,$*),,$*)' '$(RCINCLUDE)'
# Cancel GNU make built-in implicit rules