|
6 | 6 | 'use strict';
|
7 | 7 |
|
8 | 8 | const gulp = require('gulp');
|
9 |
| - |
10 | 9 | const path = require('path');
|
11 | 10 | const es = require('event-stream');
|
12 | 11 | const util = require('./lib/util');
|
13 | 12 | const task = require('./lib/task');
|
| 13 | +const common = require('./lib/optimize'); |
| 14 | +const product = require('../product.json'); |
| 15 | +const rename = require('gulp-rename'); |
| 16 | +const replace = require('gulp-replace'); |
| 17 | +const filter = require('gulp-filter'); |
| 18 | +const _ = require('underscore'); |
| 19 | +const { getProductionDependencies } = require('./lib/dependencies'); |
14 | 20 | const vfs = require('vinyl-fs');
|
| 21 | +const packageJson = require('../package.json'); |
15 | 22 | const flatmap = require('gulp-flatmap');
|
16 | 23 | const gunzip = require('gulp-gunzip');
|
17 | 24 | const File = require('vinyl');
|
18 | 25 | const fs = require('fs');
|
19 |
| -const rename = require('gulp-rename'); |
20 |
| -const filter = require('gulp-filter'); |
| 26 | +const glob = require('glob'); |
| 27 | +const { compileBuildTask } = require('./gulpfile.compile'); |
| 28 | +const { compileExtensionsBuildTask } = require('./gulpfile.extensions'); |
| 29 | +const { vscodeWebEntryPoints, vscodeWebResourceIncludes, createVSCodeWebFileContentMapper } = require('./gulpfile.vscode.web'); |
21 | 30 | const cp = require('child_process');
|
22 | 31 |
|
23 | 32 | const REPO_ROOT = path.dirname(__dirname);
|
| 33 | +const commit = util.getVersion(REPO_ROOT); |
| 34 | +const BUILD_ROOT = path.dirname(REPO_ROOT); |
| 35 | +const REMOTE_FOLDER = path.join(REPO_ROOT, 'remote'); |
| 36 | + |
| 37 | +// Targets |
24 | 38 |
|
25 | 39 | const BUILD_TARGETS = [
|
26 |
| - { platform: 'win32', arch: 'ia32', pkgTarget: 'node8-win-x86' }, |
27 |
| - { platform: 'win32', arch: 'x64', pkgTarget: 'node8-win-x64' }, |
28 |
| - { platform: 'darwin', arch: null, pkgTarget: 'node8-macos-x64' }, |
29 |
| - { platform: 'linux', arch: 'ia32', pkgTarget: 'node8-linux-x86' }, |
30 |
| - { platform: 'linux', arch: 'x64', pkgTarget: 'node8-linux-x64' }, |
31 |
| - { platform: 'linux', arch: 'armhf', pkgTarget: 'node8-linux-armv7' }, |
32 |
| - { platform: 'linux', arch: 'arm64', pkgTarget: 'node8-linux-arm64' }, |
33 |
| - { platform: 'alpine', arch: 'arm64', pkgTarget: 'node8-alpine-arm64' }, |
| 40 | + { platform: 'win32', arch: 'ia32' }, |
| 41 | + { platform: 'win32', arch: 'x64' }, |
| 42 | + { platform: 'darwin', arch: null }, |
| 43 | + { platform: 'linux', arch: 'ia32' }, |
| 44 | + { platform: 'linux', arch: 'x64' }, |
| 45 | + { platform: 'linux', arch: 'armhf' }, |
| 46 | + { platform: 'linux', arch: 'arm64' }, |
| 47 | + { platform: 'alpine', arch: 'arm64' }, |
34 | 48 | // legacy: we use to ship only one alpine so it was put in the arch, but now we ship
|
35 | 49 | // multiple alpine images and moved to a better model (alpine as the platform)
|
36 |
| - { platform: 'linux', arch: 'alpine', pkgTarget: 'node8-linux-alpine' }, |
| 50 | + { platform: 'linux', arch: 'alpine' }, |
37 | 51 | ];
|
38 | 52 |
|
39 |
| -const noop = () => { return Promise.resolve(); }; |
| 53 | +const serverResources = [ |
40 | 54 |
|
41 |
| -BUILD_TARGETS.forEach(({ platform, arch }) => { |
42 |
| - for (const target of ['reh', 'reh-web']) { |
43 |
| - gulp.task(`vscode-${target}-${platform}${arch ? `-${arch}` : ''}-min`, noop); |
| 55 | + // Bootstrap |
| 56 | + 'out-build/bootstrap.js', |
| 57 | + 'out-build/bootstrap-fork.js', |
| 58 | + 'out-build/bootstrap-amd.js', |
| 59 | + 'out-build/bootstrap-node.js', |
| 60 | + 'out-build/paths.js', |
| 61 | + |
| 62 | + // Performance |
| 63 | + 'out-build/vs/base/common/performance.js', |
| 64 | + |
| 65 | + // main entry points |
| 66 | + 'out-build/vs/server/cli.js', |
| 67 | + 'out-build/vs/server/main.js', |
| 68 | + |
| 69 | + // Watcher |
| 70 | + 'out-build/vs/platform/files/**/*.exe', |
| 71 | + 'out-build/vs/platform/files/**/*.md', |
| 72 | + |
| 73 | + // Uri transformer |
| 74 | + 'out-build/vs/server/uriTransformer.js', |
| 75 | + |
| 76 | + // Process monitor |
| 77 | + 'out-build/vs/base/node/cpuUsage.sh', |
| 78 | + 'out-build/vs/base/node/ps.sh', |
| 79 | + |
| 80 | + '!**/test/**' |
| 81 | +]; |
| 82 | + |
| 83 | +const serverWithWebResources = [ |
| 84 | + |
| 85 | + // Include all of server... |
| 86 | + ...serverResources, |
| 87 | + |
| 88 | + // ...and all of web |
| 89 | + ...vscodeWebResourceIncludes |
| 90 | +]; |
| 91 | + |
| 92 | +const serverEntryPoints = [ |
| 93 | + { |
| 94 | + name: 'vs/server/remoteExtensionHostAgent', |
| 95 | + exclude: ['vs/css', 'vs/nls'] |
| 96 | + }, |
| 97 | + { |
| 98 | + name: 'vs/server/remoteCli', |
| 99 | + exclude: ['vs/css', 'vs/nls'] |
| 100 | + }, |
| 101 | + { |
| 102 | + name: 'vs/server/remoteExtensionHostProcess', |
| 103 | + exclude: ['vs/css', 'vs/nls'] |
| 104 | + }, |
| 105 | + { |
| 106 | + name: 'vs/platform/files/node/watcher/unix/watcherApp', |
| 107 | + exclude: ['vs/css', 'vs/nls'] |
| 108 | + }, |
| 109 | + { |
| 110 | + name: 'vs/platform/files/node/watcher/nsfw/watcherApp', |
| 111 | + exclude: ['vs/css', 'vs/nls'] |
| 112 | + }, |
| 113 | + { |
| 114 | + name: 'vs/platform/files/node/watcher/parcel/watcherApp', |
| 115 | + exclude: ['vs/css', 'vs/nls'] |
| 116 | + }, |
| 117 | + { |
| 118 | + name: 'vs/platform/terminal/node/ptyHostMain', |
| 119 | + exclude: ['vs/css', 'vs/nls'] |
44 | 120 | }
|
45 |
| -}); |
| 121 | +]; |
| 122 | + |
| 123 | +const serverWithWebEntryPoints = [ |
| 124 | + |
| 125 | + // Include all of server |
| 126 | + ...serverEntryPoints, |
| 127 | + |
| 128 | + // Include workbench web |
| 129 | + ...vscodeWebEntryPoints |
| 130 | +]; |
46 | 131 |
|
47 | 132 | function getNodeVersion() {
|
48 | 133 | const yarnrc = fs.readFileSync(path.join(REPO_ROOT, 'remote', '.yarnrc'), 'utf8');
|
@@ -112,6 +197,202 @@ function nodejs(platform, arch) {
|
112 | 197 | .pipe(rename('node'));
|
113 | 198 | }
|
114 | 199 |
|
| 200 | +function packageTask(type, platform, arch, sourceFolderName, destinationFolderName) { |
| 201 | + const destination = path.join(BUILD_ROOT, destinationFolderName); |
| 202 | + |
| 203 | + return () => { |
| 204 | + const json = require('gulp-json-editor'); |
| 205 | + |
| 206 | + const src = gulp.src(sourceFolderName + '/**', { base: '.' }) |
| 207 | + .pipe(rename(function (path) { path.dirname = path.dirname.replace(new RegExp('^' + sourceFolderName), 'out'); })) |
| 208 | + .pipe(util.setExecutableBit(['**/*.sh'])) |
| 209 | + .pipe(filter(['**', '!**/*.js.map'])); |
| 210 | + |
| 211 | + const workspaceExtensionPoints = ['debuggers', 'jsonValidation']; |
| 212 | + const isUIExtension = (manifest) => { |
| 213 | + switch (manifest.extensionKind) { |
| 214 | + case 'ui': return true; |
| 215 | + case 'workspace': return false; |
| 216 | + default: { |
| 217 | + if (manifest.main) { |
| 218 | + return false; |
| 219 | + } |
| 220 | + if (manifest.contributes && Object.keys(manifest.contributes).some(key => workspaceExtensionPoints.indexOf(key) !== -1)) { |
| 221 | + return false; |
| 222 | + } |
| 223 | + // Default is UI Extension |
| 224 | + return true; |
| 225 | + } |
| 226 | + } |
| 227 | + }; |
| 228 | + const localWorkspaceExtensions = glob.sync('extensions/*/package.json') |
| 229 | + .filter((extensionPath) => { |
| 230 | + if (type === 'reh-web') { |
| 231 | + return true; // web: ship all extensions for now |
| 232 | + } |
| 233 | + |
| 234 | + const manifest = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, extensionPath)).toString()); |
| 235 | + return !isUIExtension(manifest); |
| 236 | + }).map((extensionPath) => path.basename(path.dirname(extensionPath))) |
| 237 | + .filter(name => name !== 'vscode-api-tests' && name !== 'vscode-test-resolver'); // Do not ship the test extensions |
| 238 | + const marketplaceExtensions = JSON.parse(fs.readFileSync(path.join(REPO_ROOT, 'product.json'), 'utf8')).builtInExtensions |
| 239 | + .filter(entry => !entry.platforms || new Set(entry.platforms).has(platform)) |
| 240 | + .filter(entry => !entry.clientOnly) |
| 241 | + .map(entry => entry.name); |
| 242 | + const extensionPaths = [...localWorkspaceExtensions, ...marketplaceExtensions] |
| 243 | + .map(name => `.build/extensions/${name}/**`); |
| 244 | + |
| 245 | + const extensions = gulp.src(extensionPaths, { base: '.build', dot: true }); |
| 246 | + const extensionsCommonDependencies = gulp.src('.build/extensions/node_modules/**', { base: '.build', dot: true }); |
| 247 | + const sources = es.merge(src, extensions, extensionsCommonDependencies) |
| 248 | + .pipe(filter(['**', '!**/*.js.map'], { dot: true })); |
| 249 | + |
| 250 | + let version = packageJson.version; |
| 251 | + const quality = product.quality; |
| 252 | + |
| 253 | + if (quality && quality !== 'stable') { |
| 254 | + version += '-' + quality; |
| 255 | + } |
| 256 | + |
| 257 | + const name = product.nameShort; |
| 258 | + const packageJsonStream = gulp.src(['remote/package.json'], { base: 'remote' }) |
| 259 | + .pipe(json({ name, version })); |
| 260 | + |
| 261 | + const date = new Date().toISOString(); |
| 262 | + |
| 263 | + const productJsonStream = gulp.src(['product.json'], { base: '.' }) |
| 264 | + .pipe(json({ commit, date })); |
| 265 | + |
| 266 | + const license = gulp.src(['remote/LICENSE'], { base: 'remote' }); |
| 267 | + |
| 268 | + const jsFilter = util.filter(data => !data.isDirectory() && /\.js$/.test(data.path)); |
| 269 | + |
| 270 | + const productionDependencies = getProductionDependencies(REMOTE_FOLDER); |
| 271 | + const dependenciesSrc = _.flatten(productionDependencies.map(d => path.relative(REPO_ROOT, d.path)).map(d => [`${d}/**`, `!${d}/**/{test,tests}/**`, `!${d}/.bin/**`])); |
| 272 | + const deps = gulp.src(dependenciesSrc, { base: 'remote', dot: true }) |
| 273 | + // filter out unnecessary files, no source maps in server build |
| 274 | + .pipe(filter(['**', '!**/package-lock.json', '!**/yarn.lock', '!**/*.js.map'])) |
| 275 | + .pipe(util.cleanNodeModules(path.join(__dirname, '.moduleignore'))) |
| 276 | + .pipe(jsFilter) |
| 277 | + .pipe(util.stripSourceMappingURL()) |
| 278 | + .pipe(jsFilter.restore); |
| 279 | + |
| 280 | + const nodePath = `.build/node/v${nodeVersion}/${platform}-${platform === 'darwin' ? 'x64' : arch}`; |
| 281 | + const node = gulp.src(`${nodePath}/**`, { base: nodePath, dot: true }); |
| 282 | + |
| 283 | + let web = []; |
| 284 | + if (type === 'reh-web') { |
| 285 | + web = [ |
| 286 | + 'resources/server/favicon.ico', |
| 287 | + 'resources/server/code-192.png', |
| 288 | + 'resources/server/code-512.png', |
| 289 | + 'resources/server/manifest.json' |
| 290 | + ].map(resource => gulp.src(resource, { base: '.' }).pipe(rename(resource))); |
| 291 | + } |
| 292 | + |
| 293 | + let all = es.merge( |
| 294 | + packageJsonStream, |
| 295 | + productJsonStream, |
| 296 | + license, |
| 297 | + sources, |
| 298 | + deps, |
| 299 | + node, |
| 300 | + ...web |
| 301 | + ); |
| 302 | + |
| 303 | + let result = all |
| 304 | + .pipe(util.skipDirectories()) |
| 305 | + .pipe(util.fixWin32DirectoryPermissions()); |
| 306 | + |
| 307 | + if (platform === 'win32') { |
| 308 | + result = es.merge(result, |
| 309 | + gulp.src('resources/server/bin/code.cmd', { base: '.' }) |
| 310 | + .pipe(replace('@@VERSION@@', version)) |
| 311 | + .pipe(replace('@@COMMIT@@', commit)) |
| 312 | + .pipe(replace('@@APPNAME@@', product.applicationName)) |
| 313 | + .pipe(rename(`bin/${product.applicationName}.cmd`)), |
| 314 | + gulp.src('resources/server/bin/helpers/browser.cmd', { base: '.' }) |
| 315 | + .pipe(replace('@@VERSION@@', version)) |
| 316 | + .pipe(replace('@@COMMIT@@', commit)) |
| 317 | + .pipe(replace('@@APPNAME@@', product.applicationName)) |
| 318 | + .pipe(rename(`bin/helpers/browser.cmd`)), |
| 319 | + gulp.src('resources/server/bin/server.cmd', { base: '.' }) |
| 320 | + .pipe(rename(`server.cmd`)) |
| 321 | + ); |
| 322 | + } else if (platform === 'linux' || platform === 'alpine' || platform === 'darwin') { |
| 323 | + result = es.merge(result, |
| 324 | + gulp.src('resources/server/bin/code.sh', { base: '.' }) |
| 325 | + .pipe(replace('@@VERSION@@', version)) |
| 326 | + .pipe(replace('@@COMMIT@@', commit)) |
| 327 | + .pipe(replace('@@APPNAME@@', product.applicationName)) |
| 328 | + .pipe(rename(`bin/${product.applicationName}`)) |
| 329 | + .pipe(util.setExecutableBit()), |
| 330 | + gulp.src('resources/server/bin/helpers/browser.sh', { base: '.' }) |
| 331 | + .pipe(replace('@@VERSION@@', version)) |
| 332 | + .pipe(replace('@@COMMIT@@', commit)) |
| 333 | + .pipe(replace('@@APPNAME@@', product.applicationName)) |
| 334 | + .pipe(rename(`bin/helpers/browser.sh`)) |
| 335 | + .pipe(util.setExecutableBit()), |
| 336 | + gulp.src('resources/server/bin/server.sh', { base: '.' }) |
| 337 | + .pipe(rename(`server.sh`)) |
| 338 | + .pipe(util.setExecutableBit()) |
| 339 | + ); |
| 340 | + } |
| 341 | + |
| 342 | + return result.pipe(vfs.dest(destination)); |
| 343 | + }; |
| 344 | +} |
| 345 | + |
| 346 | +['reh', 'reh-web'].forEach(type => { |
| 347 | + const optimizeTask = task.define(`optimize-vscode-${type}`, task.series( |
| 348 | + util.rimraf(`out-vscode-${type}`), |
| 349 | + common.optimizeTask({ |
| 350 | + src: 'out-build', |
| 351 | + entryPoints: _.flatten(type === 'reh' ? serverEntryPoints : serverWithWebEntryPoints), |
| 352 | + otherSources: [], |
| 353 | + resources: type === 'reh' ? serverResources : serverWithWebResources, |
| 354 | + loaderConfig: common.loaderConfig(), |
| 355 | + out: `out-vscode-${type}`, |
| 356 | + inlineAmdImages: true, |
| 357 | + bundleInfo: undefined, |
| 358 | + fileContentMapper: createVSCodeWebFileContentMapper('.build/extensions') |
| 359 | + }) |
| 360 | + )); |
| 361 | + |
| 362 | + const minifyTask = task.define(`minify-vscode-${type}`, task.series( |
| 363 | + optimizeTask, |
| 364 | + util.rimraf(`out-vscode-${type}-min`), |
| 365 | + common.minifyTask(`out-vscode-${type}`, `https://ticino.blob.core.windows.net/sourcemaps/${commit}/core`) |
| 366 | + )); |
| 367 | + gulp.task(minifyTask); |
| 368 | + |
| 369 | + BUILD_TARGETS.forEach(buildTarget => { |
| 370 | + const dashed = (str) => (str ? `-${str}` : ``); |
| 371 | + const platform = buildTarget.platform; |
| 372 | + const arch = buildTarget.arch; |
| 373 | + |
| 374 | + ['', 'min'].forEach(minified => { |
| 375 | + const sourceFolderName = `out-vscode-${type}${dashed(minified)}`; |
| 376 | + const destinationFolderName = `vscode-${type}${dashed(platform)}${dashed(arch)}`; |
| 377 | + |
| 378 | + const serverTaskCI = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}-ci`, task.series( |
| 379 | + gulp.task(`node-${platform}-${platform === 'darwin' ? 'x64' : arch}`), |
| 380 | + util.rimraf(path.join(BUILD_ROOT, destinationFolderName)), |
| 381 | + packageTask(type, platform, arch, sourceFolderName, destinationFolderName) |
| 382 | + )); |
| 383 | + gulp.task(serverTaskCI); |
| 384 | + |
| 385 | + const serverTask = task.define(`vscode-${type}${dashed(platform)}${dashed(arch)}${dashed(minified)}`, task.series( |
| 386 | + compileBuildTask, |
| 387 | + compileExtensionsBuildTask, |
| 388 | + minified ? minifyTask : optimizeTask, |
| 389 | + serverTaskCI |
| 390 | + )); |
| 391 | + gulp.task(serverTask); |
| 392 | + }); |
| 393 | + }); |
| 394 | +}); |
| 395 | + |
115 | 396 | function mixinServer(watch) {
|
116 | 397 | const packageJSONPath = path.join(path.dirname(__dirname), 'package.json');
|
117 | 398 | function exec(cmdLine) {
|
|
0 commit comments