forked from microsoft/vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
build: add watch/compile tasks for CLI (microsoft#182344)
* build: add watch/compile tasks for CLI I spent time this morning working on the 'developer experience' of the CLI in vscode, mainly getting the CLI to cross-compile chasing our initial idea of having it auto-build in a devcontainer. After some effort and disabling tunnels connections (to avoid having to pull in OpenSSL which is a huge pain to cross compile), I was able to get it to cross-compile from Linux to Windows, using the mingw linker. I could probably figure out how to get macOS working as well with more effort. However, I'm not a big fan of this, effectively it's one more 'platform' of build we need to support and test. I think a better approach is downloading the latest compiled CLI from the update server instead, as needed. That's what this PR does. It just places the CLI where it _would_ normally get compiled to by cargo; so far we don't need to do anything special outside of that. A notice is shown to users if this fallback happens. * update from review
- Loading branch information
1 parent
2929ec4
commit 2138622
Showing
7 changed files
with
255 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,5 @@ vscode.lsif | |
vscode.db | ||
/.profile-oss | ||
/cli/target | ||
/cli/openssl | ||
product.overrides.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (c) Microsoft Corporation. All rights reserved. | ||
* Licensed under the MIT License. See License.txt in the project root for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
'use strict'; | ||
|
||
//@ts-check | ||
|
||
const es = require('event-stream'); | ||
const gulp = require('gulp'); | ||
const path = require('path'); | ||
const fancyLog = require('fancy-log'); | ||
const ansiColors = require('ansi-colors'); | ||
const cp = require('child_process'); | ||
const { tmpdir } = require('os'); | ||
const { promises: fs, existsSync, mkdirSync, rmSync } = require('fs'); | ||
|
||
const task = require('./lib/task'); | ||
const watcher = require('./lib/watch'); | ||
const { debounce } = require('./lib/util'); | ||
const createReporter = require('./lib/reporter').createReporter; | ||
|
||
const root = 'cli'; | ||
const rootAbs = path.resolve(__dirname, '..', root); | ||
const src = `${root}/src`; | ||
const targetCliPath = path.join(root, 'target', 'debug', process.platform === 'win32' ? 'code.exe' : 'code'); | ||
|
||
const platformOpensslDirName = | ||
process.platform === 'win32' ? ( | ||
process.arch === 'arm64' | ||
? 'arm64-windows-static-md' | ||
: process.arch === 'ia32' | ||
? 'x86-windows-static-md' | ||
: 'x64-windows-static-md') | ||
: process.platform === 'darwin' ? ( | ||
process.arch === 'arm64' | ||
? 'arm64-osx' | ||
: 'x64-osx') | ||
: (process.arch === 'arm64' | ||
? 'arm64-linux' | ||
: process.arch === 'arm' | ||
? 'arm-linux' | ||
: 'x64-linux'); | ||
const platformOpensslDir = path.join(rootAbs, 'openssl', 'package', 'out', platformOpensslDirName); | ||
|
||
const hasLocalRust = (() => { | ||
/** @type boolean | undefined */ | ||
let result = undefined; | ||
return () => { | ||
if (result !== undefined) { | ||
return result; | ||
} | ||
|
||
try { | ||
const r = cp.spawnSync('cargo', ['--version']); | ||
result = r.status === 0; | ||
} catch (e) { | ||
result = false; | ||
} | ||
|
||
return result; | ||
}; | ||
})(); | ||
|
||
const debounceEsStream = (fn, duration = 100) => { | ||
let handle = undefined; | ||
let pending = []; | ||
const sendAll = (pending) => (event, ...args) => { | ||
for (const stream of pending) { | ||
pending.emit(event, ...args); | ||
} | ||
}; | ||
|
||
return es.map(function (_, callback) { | ||
console.log('defer'); | ||
if (handle !== undefined) { | ||
clearTimeout(handle); | ||
} | ||
|
||
handle = setTimeout(() => { | ||
handle = undefined; | ||
|
||
const previous = pending; | ||
pending = []; | ||
fn() | ||
.on('error', sendAll('error')) | ||
.on('data', sendAll('data')) | ||
.on('end', sendAll('end')); | ||
}, duration); | ||
|
||
pending.push(this); | ||
}); | ||
}; | ||
|
||
const compileFromSources = (callback) => { | ||
const proc = cp.spawn('cargo', ['--color', 'always', 'build'], { | ||
cwd: root, | ||
stdio: ['ignore', 'pipe', 'pipe'], | ||
env: existsSync(platformOpensslDir) ? { OPENSSL_DIR: platformOpensslDir, ...process.env } : process.env | ||
}); | ||
|
||
/** @type Buffer[] */ | ||
const stdoutErr = []; | ||
proc.stdout.on('data', d => stdoutErr.push(d)); | ||
proc.stderr.on('data', d => stdoutErr.push(d)); | ||
proc.on('error', callback); | ||
proc.on('exit', code => { | ||
if (code !== 0) { | ||
callback(Buffer.concat(stdoutErr).toString()); | ||
} else { | ||
callback(); | ||
} | ||
}); | ||
}; | ||
|
||
const acquireBuiltOpenSSL = (callback) => { | ||
const untar = require('gulp-untar'); | ||
const gunzip = require('gulp-gunzip'); | ||
const dir = path.join(tmpdir(), 'vscode-openssl-download'); | ||
mkdirSync(dir, { recursive: true }); | ||
|
||
cp.spawnSync( | ||
process.platform === 'win32' ? 'npm.cmd' : 'npm', | ||
['pack', '@vscode/openssl-prebuilt'], | ||
{ stdio: ['ignore', 'ignore', 'inherit'], cwd: dir } | ||
); | ||
|
||
gulp.src('*.tgz', { cwd: dir }) | ||
.pipe(gunzip()) | ||
.pipe(untar()) | ||
.pipe(gulp.dest(`${root}/openssl`)) | ||
.on('error', callback) | ||
.on('end', () => { | ||
rmSync(dir, { recursive: true, force: true }); | ||
callback(); | ||
}); | ||
}; | ||
|
||
const compileWithOpenSSLCheck = (/** @type import('./lib/reporter').IReporter */ reporter) => es.map((_, callback) => { | ||
compileFromSources(err => { | ||
if (!err) { | ||
// no-op | ||
} else if (err.toString().includes('Could not find directory of OpenSSL installation') && !existsSync(platformOpensslDir)) { | ||
fancyLog(ansiColors.yellow(`[cli]`), 'OpenSSL libraries not found, acquiring prebuilt bits...'); | ||
acquireBuiltOpenSSL(err => { | ||
if (err) { | ||
callback(err); | ||
} else { | ||
compileFromSources(err => { | ||
if (err) { | ||
reporter(err.toString()); | ||
} | ||
callback(null, ''); | ||
}); | ||
} | ||
}); | ||
} else { | ||
reporter(err.toString()); | ||
} | ||
|
||
callback(null, ''); | ||
}); | ||
}); | ||
|
||
const warnIfRustNotInstalled = () => { | ||
if (!hasLocalRust()) { | ||
fancyLog(ansiColors.yellow(`[cli]`), 'No local Rust install detected, compilation may fail.'); | ||
fancyLog(ansiColors.yellow(`[cli]`), 'Get rust from: https://rustup.rs/'); | ||
} | ||
}; | ||
|
||
const compileCliTask = task.define('compile-cli', () => { | ||
warnIfRustNotInstalled(); | ||
const reporter = createReporter('cli'); | ||
return gulp.src(`${root}/Cargo.toml`) | ||
.pipe(compileWithOpenSSLCheck(reporter)) | ||
.pipe(reporter.end(true)); | ||
}); | ||
|
||
|
||
const watchCliTask = task.define('watch-cli', () => { | ||
warnIfRustNotInstalled(); | ||
return watcher(`${src}/**`, { read: false }) | ||
.pipe(debounce(compileCliTask)); | ||
}); | ||
|
||
gulp.task(compileCliTask); | ||
gulp.task(watchCliTask); |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.