diff --git a/build/gecko_templates.mozbuild b/build/gecko_templates.mozbuild index 81030551df43..e108f5415a87 100644 --- a/build/gecko_templates.mozbuild +++ b/build/gecko_templates.mozbuild @@ -55,19 +55,27 @@ def GeckoBinary(linkage='dependent', msvcrt='dynamic', mozglue=None): error('`linkage` must be "dependent", "standalone" or None') if mozglue: - LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS'] - if mozglue == 'program': - USE_LIBS += ['mozglue'] - if CONFIG['MOZ_GLUE_IN_PROGRAM']: - if CONFIG['GNU_CC']: - LDFLAGS += ['-rdynamic'] - if CONFIG['MOZ_MEMORY']: - USE_LIBS += ['memory'] - elif mozglue == 'library': - if not CONFIG['MOZ_GLUE_IN_PROGRAM']: + if CONFIG['MOZ_CRT']: + if msvcrt == 'dynamic': + USE_LIBS += ['mozcrt'] + elif msvcrt == 'static': USE_LIBS += ['mozglue'] + else: + error('`msvcrt` must be "dynamic" or "static"') else: - error('`mozglue` must be "program" or "library"') + LDFLAGS += CONFIG['MOZ_GLUE_WRAP_LDFLAGS'] + if mozglue == 'program': + USE_LIBS += ['mozglue'] + if CONFIG['MOZ_GLUE_IN_PROGRAM']: + if CONFIG['GNU_CC']: + LDFLAGS += ['-rdynamic'] + if CONFIG['MOZ_MEMORY']: + USE_LIBS += ['memory'] + elif mozglue == 'library': + if not CONFIG['MOZ_GLUE_IN_PROGRAM']: + USE_LIBS += ['mozglue'] + else: + error('`mozglue` must be "program" or "library"') if not CONFIG['JS_STANDALONE']: USE_LIBS += [ diff --git a/build/moz.configure/toolchain.configure b/build/moz.configure/toolchain.configure index 63853f0f3d35..12a59f662fdb 100644 --- a/build/moz.configure/toolchain.configure +++ b/build/moz.configure/toolchain.configure @@ -541,12 +541,13 @@ def compiler(language, host_or_target, c_compiler=None, other_compiler=None, 'Only clang/llvm 3.4 or newer is supported.') if info.type == 'msvc': - if info.version < '19.00.23918': + if info.version < '18.00.30723' or ( + '19' < info.version < '19.00.23506'): raise FatalCheckError( 'This version (%s) of the MSVC compiler is not ' 'supported.\n' - 'You must install Visual C++ 2015 Update 2 or newer in ' - 'order to build.\n' + 'You must install Visual C++ 2013 Update 3, Visual ' + 'C++ 2015 Update 1, or newer in order to build.\n' 'See https://developer.mozilla.org/en/' 'Windows_Build_Prerequisites' % info.version) diff --git a/build/win32/mozconfig.vs2013-win64 b/build/win32/mozconfig.vs2013-win64 new file mode 100644 index 000000000000..85821f0720aa --- /dev/null +++ b/build/win32/mozconfig.vs2013-win64 @@ -0,0 +1,23 @@ +_VSPATH="/c/tools/vs2013" +export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC120.CRT + +## includes: win8.1 sdk includes, msvc std library, directx sdk for d3d9 ## +export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include + +## libs: win8.1 sdk x86 (32-bit) libs, msvc (32-bit) std library, msvc atl libs, directx sdk (32-bit) for d3d9 ## +export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib +export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib + +## paths: win8.1 sdk x86 (32-bit) tools, msvc (64-bit compiling 32-bit) build toolchain, moz tools ## +export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64_x86:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}" + +## WindowsSDKDir ## +export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.1/" + +. $topsrcdir/build/mozconfig.vs-common + +mk_export_correct_style LIB +mk_export_correct_style LIBPATH +mk_export_correct_style PATH +mk_export_correct_style INCLUDE +mk_export_correct_style WIN32_REDIST_DIR diff --git a/build/win64/mozconfig.vs2013 b/build/win64/mozconfig.vs2013 new file mode 100644 index 000000000000..5fbde2df738b --- /dev/null +++ b/build/win64/mozconfig.vs2013 @@ -0,0 +1,23 @@ +_VSPATH="/c/tools/vs2013" +export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x64/Microsoft.VC120.CRT + +## includes: win8.1 sdk includes, msvc std library, directx sdk for d3d9 ## +export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include + +## libs: win8.1 sdk x64 (64-bit) libs, msvc (64-bit) std library, msvc atl libs, directx sdk (64-bit) for d3d9 ## +export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64 +export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x64:${_VSPATH}/vc/lib/amd64:${_VSPATH}/vc/atlmfc/lib/amd64:/c/tools/sdks/dx10/lib/x64 + +## paths: win8.1 sdk x64 (64-bit) tools, msvc (64-bit) build toolchain, moz tools ## +export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x64:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/VC/BIN/x86_amd64:${_VSPATH}/VC/BIN:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:${PATH}" + +## WindowsSDKDir ## +export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.1/" + +. $topsrcdir/build/mozconfig.vs-common + +mk_export_correct_style LIB +mk_export_correct_style LIBPATH +mk_export_correct_style PATH +mk_export_correct_style INCLUDE +mk_export_correct_style WIN32_REDIST_DIR diff --git a/config/external/nss/Makefile.in b/config/external/nss/Makefile.in index b3a17bfea5fa..f3f3abe25155 100644 --- a/config/external/nss/Makefile.in +++ b/config/external/nss/Makefile.in @@ -367,7 +367,12 @@ endif # Can't pass this in DEFAULT_GMAKE_FLAGS because that overrides # definitions in NSS, so just export it into the sub-make's environment. ifeq (WINNT_1,$(OS_TARGET)_$(MOZ_MEMORY)) +ifdef MOZ_CRT +# OS_LIBS comes from having mozcrt as a dependency in moz.build. +DLLFLAGS := $(OS_LIBS) +else DLLFLAGS := -LIBPATH:$(ABS_DIST)/../mozglue/build -DEFAULTLIB:mozglue +endif export DLLFLAGS endif diff --git a/config/recurse.mk b/config/recurse.mk index 998c9310bb97..6316f7c27f72 100644 --- a/config/recurse.mk +++ b/config/recurse.mk @@ -168,6 +168,9 @@ endif ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library) mozglue/build/target memory/replace/logalloc/replay/target: memory/replace/dummy/target endif +ifdef MOZ_CRT +mozglue/crt/target: mozglue/build/target +endif # js/src/target can end up invoking js/src/host rules (through object files # depending on jsautokw.h, which depends on host_jskwgen, and that can't # happen at the same time (bug #1146738) diff --git a/js/src/old-configure.in b/js/src/old-configure.in index 5900f889e08a..9c8ff3583601 100644 --- a/js/src/old-configure.in +++ b/js/src/old-configure.in @@ -215,6 +215,12 @@ case "$target" in AC_DEFINE(_USE_MATH_DEFINES) # Otherwise MSVC's math.h doesn't #define M_PI. case "$CC_VERSION" in + 18*) + _CC_SUITE=12 + MSVS_VERSION=2013 + MSVC_C_RUNTIME_DLL=msvcr120.dll + MSVC_CXX_RUNTIME_DLL=msvcp120.dll + ;; 19*) _CC_SUITE=14 MSVS_VERSION=2015 @@ -1909,6 +1915,7 @@ if test "$MOZ_MEMORY"; then ;; esac fi +AC_SUBST(MOZ_CRT) AC_SUBST(MOZ_GLUE_IN_PROGRAM) AC_SUBST_LIST(MOZ_GLUE_WRAP_LDFLAGS) diff --git a/mozglue/build/moz.build b/mozglue/build/moz.build index 26fc0799766b..1183320c57e0 100644 --- a/mozglue/build/moz.build +++ b/mozglue/build/moz.build @@ -11,7 +11,8 @@ if CONFIG['OS_TARGET'] in ('WINNT', 'Darwin', 'Android'): else: Library('mozglue') -SDK_LIBRARY = True +if not CONFIG['MOZ_CRT']: + SDK_LIBRARY = True if CONFIG['OS_TARGET'] == 'Android': SOURCES += [ diff --git a/mozglue/crt/Makefile.in b/mozglue/crt/Makefile.in new file mode 100644 index 000000000000..b1628b151729 --- /dev/null +++ b/mozglue/crt/Makefile.in @@ -0,0 +1,89 @@ +# +# 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/. + +# Roll our own custom logic here for the import library + +############################################################################### +# +# Linking Mozilla itself to jemalloc is not particularly difficult. To do this +# we avoid linking directly to the Microsoft-provided CRT import libraries. +# Instead, we link to our own import library which we generate here. To +# replace the CRT's malloc/free/other memory management symbols we export +# our own versions out of jemalloc.dll. We then take the import library that +# the compiler generates for jemalloc.dll and combine it with the MS CRT import +# libraries. We put our library on the command line first, and the CRT symbols +# are discarded in favor of our versions! +# +# Unfortunately that was too easy. The CRT import library is not a standard +# import library that contains a list of symbols and whatnot. It also includes +# object files that are linked into generated programs. One of these, +# crtdll.obj is (as one might expect) linked into all DLLs that link against +# the CRT. This file does things like run static C++ constructors when the +# DLL is attached, call DllMain, etc. +# +# In the CRT source all malloc/free calls are made to malloc_crt and free_crt. +# In debug builds these are both defined to malloc_dbg and free_dbg. In opt +# builds malloc_crt is an actual function, implemented and exposed from the +# CRT. free_crt is, however, defined to be just plain old free. This works +# fine inside the CRT where malloc_crt and free operate on the same heap. +# Outside the CRT malloc_crt is in the CRT's heap, but free is in jemalloc's +# heap. This causes much pain at shutdown :-( +# +# The obvious solution here is to override malloc_crt too. Unfortunately, +# that doesn't work because the CRT expects to be able to call msize on this +# piece of memory deep inside the CRT, which will fail because it'll call the +# CRT's msize on a pointer in jemalloc's heap. +# +# Our solution to this is quite devious. We take apart the CRT's import lib +# and remove the problematic object file. We then poke at the object file's +# symbol table and replace '__imp__free' (which means grab free from some +# other DLL) with '__imp__frex'. Then we define our own dummy no-op function +# in jemalloc.dll and export it as frex. Then we put the CRT import lib +# back together with the patched crtdll.obj, glue it to the end of jemalloc's +# import library and link the rest of Mozilla to that. +# +# The result? A binary that uses jemalloc, doesn't crash, and leaks a tiny +# amount of memory (32 words per DLL in the 2010 CRT) at shutdown. +# +############################################################################### + +target:: mozcrt.lib + $(INSTALL) $(IFLAGS2) mozcrt.lib $(DIST)/lib + +# And finally combine that with the jemalloc import library to get an import +# library that has our malloc/free/etc and the CRT's everything else +mozcrt.lib: ../build/mozglue.lib msvc_modified.lib + lib -OUT:$@ $^ + +# Put the fixed object file back in +msvc_modified.lib: msvc_removed.lib crtdll_fixed.obj + lib -OUT:$@ $^ + +# Fix the object file +crtdll_fixed.obj: crtdll.obj + $(PYTHON) $(srcdir)/fixcrt.py + +# Find the path of crtdll.obj +CRTDLL_FULLPATH=$(subst \,\\,$(shell lib -list msvc_combined.lib | grep crtdll\\.obj)) + +# Remove the broken object file, only after we have extracted it +msvc_removed.lib: msvc_combined.lib crtdll.obj + lib -OUT:$@ msvc_combined.lib -REMOVE:$(CRTDLL_FULLPATH) + +# Extract the broken object file out of the combined library +crtdll.obj: msvc_combined.lib + lib -OUT:$@ $^ -EXTRACT:$(CRTDLL_FULLPATH) + +# Grab both CRT libraries and combine them into one library to simplify things +msvc_combined.lib: + lib -OUT:$@ $(WIN32_CRT_LIBS) + +# Normally, we'd use SDK_LIBRARY, but we can't because all the tricks above +# involve *not* defining the library in moz.build, so SDK_LIBRARY = True would +# not have the expected outcome. +SDK_FILES = mozcrt.lib +SDK_DEST = $(SDK_LIB_DIR) +SDK_TARGET = target +INSTALL_TARGETS += SDK diff --git a/mozglue/crt/fixcrt.py b/mozglue/crt/fixcrt.py new file mode 100644 index 000000000000..3baa935f22a7 --- /dev/null +++ b/mozglue/crt/fixcrt.py @@ -0,0 +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/. + +from __future__ import with_statement + +with open('crtdll.obj', 'rb') as infile: + data = infile.read() + with open('crtdll_fixed.obj', 'wb') as outfile: + # for Win32 + data = data.replace('__imp__free', '__imp__frex') + # for Win64 + data = data.replace('__imp_free', '__imp_frex') + outfile.write(data) diff --git a/mozglue/crt/moz.build b/mozglue/crt/moz.build new file mode 100644 index 000000000000..b0084367bf35 --- /dev/null +++ b/mozglue/crt/moz.build @@ -0,0 +1,16 @@ +# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +Library('mozcrt') + +STATIC_LIBRARY_NAME = 'mozcrt_s' + +OS_LIBS += [ + '-NODEFAULTLIB:msvcrt', + '-NODEFAULTLIB:msvcprt', + '-LIBPATH:%s/mozglue/crt' % TOPOBJDIR, + '-DEFAULTLIB:mozcrt', +] diff --git a/mozglue/moz.build b/mozglue/moz.build index 0938dc37282a..d2fa07e814de 100644 --- a/mozglue/moz.build +++ b/mozglue/moz.build @@ -15,5 +15,8 @@ DIRS += [ 'misc', ] +if CONFIG['MOZ_CRT']: + DIRS += ['crt'] + if not CONFIG['JS_STANDALONE']: TEST_DIRS += ['tests'] diff --git a/old-configure.in b/old-configure.in index 56736ffd401c..064e7596a33a 100644 --- a/old-configure.in +++ b/old-configure.in @@ -321,6 +321,12 @@ case "$target" in AC_DEFINE(_USE_MATH_DEFINES) # Otherwise MSVC's math.h doesn't #define M_PI. case "$CC_VERSION" in + 18*) + _CC_SUITE=12 + MSVS_VERSION=2013 + MSVC_C_RUNTIME_DLL=msvcr120.dll + MSVC_CXX_RUNTIME_DLL=msvcp120.dll + ;; 19*) _CC_SUITE=14 MSVS_VERSION=2015 @@ -5394,11 +5400,24 @@ else case "${target}" in *-mingw*) export MOZ_NO_DEBUG_RTL=1 + if test "$MSVS_VERSION" != "2015"; then + WIN32_CRT_LIBS="msvcrt.lib msvcprt.lib" + dnl Look for a broken crtdll.obj + WIN32_CRTDLL_FULLPATH=`lib -nologo -list $WIN32_CRT_LIBS | grep crtdll\\.obj` + lib -NOLOGO -OUT:crtdll.obj $WIN32_CRT_LIBS -EXTRACT:$WIN32_CRTDLL_FULLPATH + if grep -q '__imp__\{0,1\}free' crtdll.obj; then + MOZ_CRT=1 + fi + rm crtdll.obj + fi ;; esac fi # MOZ_MEMORY AC_SUBST(MOZ_SYSTEM_JEMALLOC) +AC_SUBST(MOZ_CRT) +export MOZ_CRT AC_SUBST(MOZ_GLUE_IN_PROGRAM) +AC_SUBST_LIST(WIN32_CRT_LIBS) # Allow the application to provide a subconfigure script. # This should be after 'export MOZ_NO_DEBUG_RTL=1' since diff --git a/python/mozbuild/mozbuild/backend/visualstudio.py b/python/mozbuild/mozbuild/backend/visualstudio.py index 86e97d13d3ce..f5271a773e53 100644 --- a/python/mozbuild/mozbuild/backend/visualstudio.py +++ b/python/mozbuild/mozbuild/backend/visualstudio.py @@ -38,13 +38,17 @@ def get_id(name): return str(uuid.uuid5(uuid.NAMESPACE_URL, name)).upper() def visual_studio_product_to_solution_version(version): - if version == '2015': + if version == '2013': + return '12.00', '12' + elif version == '2015': return '12.00', '14' else: raise Exception('Unknown version seen: %s' % version) def visual_studio_product_to_platform_toolset_version(version): - if version == '2015': + if version == '2013': + return 'v120' + elif version == '2015': return 'v140' else: raise Exception('Unknown version seen: %s' % version)