summaryrefslogtreecommitdiff
path: root/src/mongo/installer/msi/SConscript
blob: 099d29432c25edbbf745c2bf3475aeff662b0ffc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# -*- mode: python; -*-

import os

Import("env")
Import("get_option")
Import("has_option")

if not env.TargetOSIs('windows'):
    Return()

import re
import subprocess
import winreg

env = env.Clone()

env.SConscript(
    dirs=[
        'ca',
    ],
    exports=[
        'env',
    ],
)

env['WIX'] = os.environ.get('WIX')
env['WIXPATH'] = r'$WIX\bin'
env['WIXHEAT'] = r'$WIXPATH\heat.exe'
env['WIXCANDLE'] = r'$WIXPATH\candle.exe'
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")
    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",
            "UIFragment.wxs",
            ]

# Need to do this in order to get scons to translate path separators into native format
buildDir = env.Dir("$BUILD_DIR").path
if has_option("use-new-tools"):
	toolBuildDir = "src\mongo-tools"
else:
	toolBuildDir = buildDir + r'\mongo'

enterprisebase = 'src\mongo\db\modules\enterprise'
enterpriseToolBuildDir = buildDir + r'\mongo\db\modules\enterprise'

# Set up parameters to pass to wix -
#
# msi_edition - "Enterprise" or "Standard"
# msi_platform - "x64" or "x86"
# msi_flavor - "2008R2Plus" or ""
#

msi_flavor = '2008R2Plus'
msi_platform = 'x64'

# Enterprise
if 'enterprise' in env['MONGO_MODULES']:
  msi_edition = 'Enterprise'
  upgrade_code = 'ccd97a61-fd75-4645-b6a9-f1cd4b8235c1'
# Community
else:
  if get_option('ssl') == 'on':
    msi_edition = 'SSL'
    upgrade_code = 'ea0c66de-dc03-4c28-9f2b-60edacc44ed7'
  else:
    msi_edition = 'Standard'
    upgrade_code = '45544685-4981-4f1d-a1fe-302539b110bf'

sourcesList.append("Installer_64.wxs")

sources = ["wxs/" + file for file in sourcesList]
objects = ["$BUILD_DIR/msi/" + file.replace(".wxs", ".wixobj") for file in sourcesList]

full_version = env['MONGO_VERSION'].partition('-')[0]

# major version is the x.y, not the x.y.z
major_version = full_version
mv = major_version.split('.')
major_version = "%s.%s" % (mv[0], mv[1])

# We must regenerate the upgrade codes for each major release.
# i.e., 3.0, 3.2, 3.4 need new codes but not 3.2.1, 3.2.2, etc
# The build will now fail when the major version is bumped to prevent mistakes.
# When the upgrade codes are bumped, remember to raise the version number to the next major version.
# On each update to the upgrade codes:
# 1. Generate new GUIDs
# 2. Ensure each MSI gets a different GUID. This is used to identify products.
#    It allows upgrade from 3.2.0 to 3.2.1 in place instead of side-by-side.
# 3. Update the check for the next major release below so we bump the GUIDs in the future.
#
if float(major_version) > 4.4:
    # If you are troubleshooting this error, see the comment above
    env.FatalError("The upgrade codes are out of date for this release. Please \n" +
    "replace the existing GUIDs listed in this file with new GUIDs so " +
    "side-by-side installation of major versions (i.e. 3.2, and 3.4) is " +
    "supported.")

# Currently, we are planning to key the same upgrade code for each
# (msi_edition, msi_platform, msi_flavor) combination
# and change MSI ProductId on minor updates, 2.6.0 -> 2.6.1, we let Wix do automatic
# GUID generation for us rather then build a database of GUIDs in our build system
# For major updates, we are going to create a new directory/productid/upgrade_code ie, 2.6 -> 3.0


# candle: compile .wxs files into .wixobjs
env.Command(objects,
            sources,
            '"$WIXCANDLE" -wx'
            # cannot have anything other than x.x.x.x in version string.
            # we should choose a fourth version number that reflects pre-ness.
            ' -dMongoDBMajorVersion=' + major_version +
            ' -dMongoDBVersion=' + full_version +
            ' -dLicenseSource=distsrc'
            r' -dEnterpriseBase=' + enterprisebase + '\\'
            ' -dBinarySource=' + buildDir + r'\mongo'
            ' -dToolBinarySource=' + toolBuildDir +
            ' -dEnterpriseToolBinarySource=' + enterpriseToolBuildDir +
            ' -dMergeModulesBasePath="$MERGEMODULESBASEPATH"'
            ' -dEdition=' + msi_edition +
            ' -d"ProductId=*\"'
            ' -dUpgradeCode=' + upgrade_code +
            ' -dCustomActionDll=' + buildDir + r'\mongo\installer\msi\ca\mongoca.dll'
            ' -dConfiguration=Release'
            ' -dOutDir=' + buildDir + r'\msi'
            ' -dPlatform=' + msi_platform +
            ' -dFlavor=' + msi_flavor +
            r' -dProjectDir=buildscripts\packaging\msi\\'
            ' -dProjectName=MongoDB'
            ' -dCompassDir=' + buildDir + r'\mongo\installer\compass'
            ' -dTargetDir=' + buildDir + r'\msi'
            ' -dTargetExt=.msi'
            ' -dTargetFileName=${SERVER_ARCHIVE}'
            r' -dSaslSource=c:\sasl\bin'
            r' -dSnmpSource=c:\snmp\bin'
            r' -dSslSource=' + env['WINDOWS_OPENSSL_BIN'] +
            ' -out ' + buildDir + r'\msi\\'
            ' -arch ' + msi_platform +
            ' -ext "$WIXUIEXT"'
            ' -ext "$WIXUTILEXT"'
            ' $SOURCES')

#light: link .objs into an msi
pre_msi = "$BUILD_DIR/msi/${SERVER_DIST_BASENAME}.pre.msi"

# Suppress VC140_CRT_CRT.MSM Internal Consistency Errors
# ICE03 - Supress "String overflow"
# -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa369037(v=vs.85).aspx
# ICE82 - Suppress "duplicate sequence number"
# -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa368798(v=vs.85).aspx
# ICE30 - Suppress "different components install same file"
# -- mongod.exe is installed in two different components but only one is ever used during an install
#    so this consistency check can be ignored.
# -- https://msdn.microsoft.com/en-us/library/windows/desktop/aa368954(v=vs.85).aspx

pre_msi_cmd = env.Command(pre_msi,
            objects,
            '"$WIXLIGHT" -out ${TARGET} -wx -cultures:null -sice:ICE82  -sice:ICE03 -sice:ICE30'
            ' -ext "$WIXUIEXT"'
            ' -ext "$WIXUTILEXT"'
            ' ${SOURCES}')
env.NoCache(pre_msi_cmd)

# Generated Dependencies
env.Depends(pre_msi_cmd, '$BUILD_DIR/mongo/mongo.exe')
env.Depends(pre_msi_cmd, '$BUILD_DIR/mongo/mongod.exe')
env.Depends(pre_msi_cmd, '$BUILD_DIR/mongo/mongos.exe')
env.Depends(pre_msi_cmd, '$BUILD_DIR/mongo/installer/msi/ca/mongoca.dll')
env.Depends(pre_msi_cmd, '$BUILD_DIR/mongo/installer/compass/Install-Compass.ps1')

# Source Dependencies
env.Depends(pre_msi_cmd, '#buildscripts/packaging/msi/mongod.yaml')

if 'enterprise' in env['MONGO_MODULES']:
    env.Depends(pre_msi_cmd, "#" + enterpriseToolBuildDir + "/mongodecrypt.exe")
    env.Depends(pre_msi_cmd, "#" + enterpriseToolBuildDir + "/mongoldap.exe")
    env.Depends(pre_msi_cmd, "#" + enterpriseToolBuildDir + "/mongocryptd.exe")

msi = "$BUILD_DIR/msi/${SERVER_DIST_BASENAME}.msi"
env.Command(msi,
            pre_msi,
            r'$PYTHON buildscripts\msitrim.py ${SOURCES} ${TARGET}')
env.AlwaysBuild(msi)
env.NoCache(msi)

env.Alias( "msi" , msi )