diff options
author | Andrew Morrow <andrew.morrow@10gen.com> | 2019-12-08 01:30:07 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-12-08 01:30:07 +0000 |
commit | 7c428b6fba15eb2058d52430b8d2c5f4df45d7ad (patch) | |
tree | 093999b7fcc63cc9b185a51a315c428272240c95 | |
parent | 72788deb99186ac2628604505147e68ac53cffc5 (diff) | |
download | mongo-7c428b6fba15eb2058d52430b8d2c5f4df45d7ad.tar.gz |
SERVER-44557 Set the default for MSVC_VERSION to VS2017
-rw-r--r-- | SConstruct | 5 | ||||
-rw-r--r-- | site_scons/site_tools/vcredist.py | 199 | ||||
-rw-r--r-- | src/mongo/installer/msi/SConscript | 37 | ||||
-rw-r--r-- | src/mongo/installer/msi/wxs/BinaryFragment.wxs | 2 |
4 files changed, 207 insertions, 36 deletions
diff --git a/SConstruct b/SConstruct index 8fc25fbadc4..67325c76c8e 100644 --- a/SConstruct +++ b/SConstruct @@ -624,7 +624,7 @@ def variable_arch_converter(val): def decide_platform_tools(): if mongo_platform.is_running_os('windows'): # we only support MS toolchain on windows - return ['msvc', 'mslink', 'mslib', 'masm'] + return ['msvc', 'mslink', 'mslib', 'masm', 'vcredist'] elif mongo_platform.is_running_os('linux', 'solaris'): return ['gcc', 'g++', 'gnulink', 'ar', 'gas'] elif mongo_platform.is_running_os('darwin'): @@ -846,7 +846,8 @@ env_vars.Add('MSVC_USE_SCRIPT', help='Sets the script used to setup Visual Studio.') env_vars.Add('MSVC_VERSION', - help='Sets the version of Visual Studio to use (e.g. 12.0, 11.0, 10.0)') + help='Sets the version of Visual C++ to use (e.g. 14.1 for VS2017, 14.2 for VS2019)', + default="14.1") env_vars.Add('NINJA_SUFFIX', help="""A suffix to add to the end of generated build.ninja diff --git a/site_scons/site_tools/vcredist.py b/site_scons/site_tools/vcredist.py new file mode 100644 index 00000000000..62e14010329 --- /dev/null +++ b/site_scons/site_tools/vcredist.py @@ -0,0 +1,199 @@ +# Copyright 2019 MongoDB Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import re +import subprocess +import winreg + +import SCons + +def exists(env): + result = 'msvc' in env['TOOLS'] + return result + +# How to locate the Merge Modules path is described in: +# +# - VS2019: https://docs.microsoft.com/en-us/visualstudio/releases/2019/redistribution#visual-c-runtime-files +# - VS2017: https://docs.microsoft.com/en-us/visualstudio/productinfo/2017-redistribution-vs#visual-c-runtime-files +# - VS2015: https://docs.microsoft.com/en-us/visualstudio/productinfo/2015-redistribution-vs#visual-c-runtime +# +# However, please note that for VS2017 an VS2019, the documented paths are incorrect, per this +# discussion: +# +# - https://developercommunity.visualstudio.com/content/problem/828060/what-are-the-correct-location-to-search-for-vc-crt.html +# +# This tool uses the currently undocumented but correct paths. + +# The keys are the values SCons accepts for TARGET_ARCH to name +# different windows targets, the values are the tag that VS uses +# for the associated redistributable for that platform. +# +# TODO: Expand this map as needed. +target_arch_expansion_map = { + 'amd64' : 'x64', + 'arm' : None, + 'arm64' : 'arm64', + 'emt64' : 'x64', + 'i386' : 'x86', + 'x86' : 'x86', + 'x86_64' : 'x64', +} + +def _get_programfiles(): + result = os.getenv('ProgramFiles(x86)') + # When we run this under cygwin, the environment is broken, fall + # back to hard coded C:\Program Files (x86) + if result is None: + result = "C:\\Program Files (x86)" + if not os.path.isdir(result): + return None + return result + +def _get_merge_module_name_for_feature(env, feature): + version_components = env['MSVC_VERSION'].split('.') + return "Microsoft_VC{msvc_major}{msvc_minor}_{feature}_{target_arch}.msm".format( + msvc_major=version_components[0], + msvc_minor=version_components[1], + feature=feature, + target_arch=target_arch_expansion_map[env.subst('$TARGET_ARCH')] + ) + +def generate(env): + if not exists(env): + return + + env.Tool('msvc') + + env.AddMethod(_get_merge_module_name_for_feature, "GetMergeModuleNameForFeature") + + # Obtain the major and minor versions of the curently configured MSVC + # and ensure that we are using a VC 14 based toolchain. + # + # Please see + # https://en.wikipedia.org/wiki/Microsoft_Visual_C%2B%2B#Internal_version_numbering + # for details on the various version numbers in play for + # the Microsoft toolchain. + msvc_major, msvc_minor = env['MSVC_VERSION'].split('.') + if msvc_major != "14": + return + + # We may or may not need to figure out the path to Program files, + # depending on the various paths we take throught this logic. + programfilesx86 = None + + # TODO: Getting this path is a start, but we should later provide + # an abstraction over the names of the merge modules + # themselves. They seem to have the form + # Microsoft_VC{msvc_major}{msvc_minor}_{Feature}_{target_arch}.msm. It + # would be useful to provide an env.MergeModuleNameFor('feature') + # that consulted the values we have found here and used + # TARGET_ARCH (normalized somehow) to select the right one. + mergemodulepath = None + + # On VS2015 the merge modules are in the program files directory, + # not under the VS install dir. + if msvc_minor == '0': + + if not programfilesx86: + programfilesx86 = _get_programfiles() + if not programfilesx86: + return + + mergemodulepath = os.path.join(programfilesx86, "Common Files", "Merge Modules") + if os.path.isdir(mergemodulepath): + env['MSVS']['VCREDISTMERGEMODULEPATH'] = mergemodulepath + + if not 'VSINSTALLDIR' in env['MSVS']: + + # Compute a VS version based on the VC version. VC 14.0 is VS 2015, VC + # 14.1 is VS 2017. Also compute the next theoretical version by + # incrementing the major version by 1. Then form a range from this + # that we can use as an argument to the -version flag to vswhere. + vs_version = int(msvc_major) + int(msvc_minor) + vs_version_next = vs_version + 1 + vs_version_range = '[{vs_version}.0, {vs_version_next}.0)'.format(vs_version=vs_version, vs_version_next=vs_version_next) + + if not programfilesx86: + programfilesx86 = _get_programfiles() + if not programfilesx86: + return + + # Use vswhere (it has a fixed stable path) to query where Visual Studio is installed. + env['MSVS']['VSINSTALLDIR'] = subprocess.check_output([os.path.join(programfilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe"), "-version", vs_version_range, "-property", "installationPath", "-nologo"]).decode('utf-8').strip() + + vsinstall_dir = env['MSVS']['VSINSTALLDIR'] + + # Combine and set the full merge module path + redist_root = os.path.join(vsinstall_dir, "VC", "Redist", "MSVC") + if not os.path.isdir(redist_root): + return + env['MSVS']['VCREDISTROOT'] = redist_root + + # Check the registry key that has the runtime lib version + try: + # TOOO: This x64 needs to be abstracted away. Is it the host + # arch, or the target arch? My guess is host. + vsruntime_key_name = "SOFTWARE\\Microsoft\\VisualStudio\\{msvc_major}.0\\VC\\Runtimes\\x64".format(msvc_major=msvc_major) + vsruntime_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, vsruntime_key_name) + vslib_version, vslib_version_type = winreg.QueryValueEx(vsruntime_key, "Version") + except WindowsError: + return + + # Fallback to directory search if we don't find the expected version + redist_path = os.path.join(redist_root, re.match("v(\d+\.\d+\.\d+)\.\d+", vslib_version).group(1)) + if not os.path.isdir(redist_path): + redist_path = None + dirs = os.listdir(redist_root) + dirs.sort() + for dir in reversed(dirs): + candidate = os.path.join(redist_root, dir) + if os.path.isdir(candidate): + redist_path = candidate + break + else: + return + env['MSVS']['VCREDISTPATH'] = redist_path + + if mergemodulepath is None and msvc_minor != "0": + mergemodulepath = os.path.join(redist_path, "MergeModules") + if os.path.isdir(mergemodulepath): + env['MSVS']['VCREDISTMERGEMODULEPATH'] = mergemodulepath + + # Keep these in preference order. The way with the {} in between + # the dots appears to be the more modern form, but we select the + # older one when available to minimize disruption to existing + # automation that expects the redist executable embedded in our + # packages to have this shape. Some architectures, like arm64, + # don't appear to be provided under that syntax though, so we + # include the newer form for that purpose. If Microsoft ever stops + # providing the old form, we will automatically roll forward to + # the new form. + vcredist_search_template_sequence = [ + "vcredist_{}.exe", + "vc_redist.{}.exe", + ] + + expansion = target_arch_expansion_map.get(env.subst('$TARGET_ARCH'), None) + if not expansion: + return + + vcredist_candidates = [c.format(expansion) for c in vcredist_search_template_sequence] + for candidate in vcredist_candidates: + candidate = os.path.join(redist_path, candidate) + if os.path.isfile(candidate): + break + else: + return + env['MSVS']['VCREDISTEXE'] = candidate diff --git a/src/mongo/installer/msi/SConscript b/src/mongo/installer/msi/SConscript index 099d29432c2..b8db8f409fa 100644 --- a/src/mongo/installer/msi/SConscript +++ b/src/mongo/installer/msi/SConscript @@ -32,40 +32,10 @@ env['WIXLIGHT'] = r'$WIXPATH\light.exe' env['WIXUIEXT'] = r'$WIXPATH\WixUIExtension.dll'
env['WIXUTILEXT'] = r'$WIXPATH\WixUtilExtension.dll'
-# How to locate the Merge Modules path is described in https://docs.microsoft.com/en-us/cpp/ide/redistributing-visual-cpp-files?view=vs-2017
-
-# When we run this on evergreen, the environment is broken, fall back to hard coded C:\Program Files (x86)
-programfilesx86 = os.environ.get('ProgramFiles(x86)')
-if programfilesx86 is None:
- programfilesx86 = "C:\\Program Files (x86)"
-
-# Use vswhere (it has a fixed stable path) to query where Visual Studio is installed.
-vsinstall_path = subprocess.check_output([os.path.join(programfilesx86, "Microsoft Visual Studio", "Installer", "vswhere.exe"), "-version", "[15.0,16.0)", "-property", "installationPath", "-nologo"]).decode('utf-8').strip()
-
-# Check the registry key that has the runtime lib version
-try:
- vsruntime_key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64")
- vslib_version,vslib_version_type = winreg.QueryValueEx(vsruntime_key, "Version")
-except WindowsError:
- print("Visual Studio Runtime not found in registry, disabling msi installer")
+if not 'VCREDISTMERGEMODULEPATH' in env['MSVS']:
+ print("SCons tool setup did not configure the path to the vcredist merge modules, disabling MSI installer")
Return()
-# Combine and set the full merge module path
-redist_root = os.path.join(vsinstall_path, "VC", "Redist", "MSVC")
-redist_path = os.path.join(redist_root, re.match("v(\d+\.\d+\.\d+)\.\d+", vslib_version).group(1))
-
-# Fallback to directory search if we don't find the expected version
-if not os.path.isdir(redist_path):
- dirs = os.listdir(redist_root)
- dirs.sort()
- for dir in reversed(dirs):
- candidate = os.path.join(redist_root, dir)
- if os.path.isdir(candidate):
- redist_path = candidate
- break
-
-env['MERGEMODULESBASEPATH'] = os.path.join(redist_path, "MergeModules")
-
sourcesList = [ "BinaryFragment.wxs",
"FeatureFragment.wxs",
"LicensingFragment.wxs",
@@ -154,7 +124,8 @@ env.Command(objects, ' -dBinarySource=' + buildDir + r'\mongo'
' -dToolBinarySource=' + toolBuildDir +
' -dEnterpriseToolBinarySource=' + enterpriseToolBuildDir +
- ' -dMergeModulesBasePath="$MERGEMODULESBASEPATH"'
+ ' -dMergeModulesBasePath=' + "\"${MSVS['VCREDISTMERGEMODULEPATH']}\"" +
+ ' -dMergeModuleFileCRT=' + env.GetMergeModuleNameForFeature('CRT') +
' -dEdition=' + msi_edition +
' -d"ProductId=*\"'
' -dUpgradeCode=' + upgrade_code +
diff --git a/src/mongo/installer/msi/wxs/BinaryFragment.wxs b/src/mongo/installer/msi/wxs/BinaryFragment.wxs index 2a03699b614..06b0c8465dd 100644 --- a/src/mongo/installer/msi/wxs/BinaryFragment.wxs +++ b/src/mongo/installer/msi/wxs/BinaryFragment.wxs @@ -164,7 +164,7 @@ <?if $(var.Edition) = Enterprise or $(var.Edition) = SSL ?>
<DirectoryRef Id="TARGETDIR">
- <Merge Id="m_vcredist" SourceFile="$(var.MergeModulesBasePath)\Microsoft_VC141_CRT_x64.msm" DiskId="1" Language="0"/>
+ <Merge Id="m_vcredist" SourceFile="$(var.MergeModulesBasePath)\$(var.MergeModuleFileCRT)" DiskId="1" Language="0"/>
</DirectoryRef>
<?endif ?>
|