Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/npm/postinstall.ts
4770 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as fs from 'fs';
7
import path from 'path';
8
import * as os from 'os';
9
import * as child_process from 'child_process';
10
import { dirs } from './dirs.ts';
11
12
const npm = process.platform === 'win32' ? 'npm.cmd' : 'npm';
13
const root = path.dirname(path.dirname(import.meta.dirname));
14
15
function log(dir: string, message: string) {
16
if (process.stdout.isTTY) {
17
console.log(`\x1b[34m[${dir}]\x1b[0m`, message);
18
} else {
19
console.log(`[${dir}]`, message);
20
}
21
}
22
23
function run(command: string, args: string[], opts: child_process.SpawnSyncOptions) {
24
log(opts.cwd as string || '.', '$ ' + command + ' ' + args.join(' '));
25
26
const result = child_process.spawnSync(command, args, opts);
27
28
if (result.error) {
29
console.error(`ERR Failed to spawn process: ${result.error}`);
30
process.exit(1);
31
} else if (result.status !== 0) {
32
console.error(`ERR Process exited with code: ${result.status}`);
33
process.exit(result.status);
34
}
35
}
36
37
function npmInstall(dir: string, opts?: child_process.SpawnSyncOptions) {
38
opts = {
39
env: { ...process.env },
40
...(opts ?? {}),
41
cwd: dir,
42
stdio: 'inherit',
43
shell: true
44
};
45
46
const command = process.env['npm_command'] || 'install';
47
48
if (process.env['VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME'] && /^(.build\/distro\/npm\/)?remote$/.test(dir)) {
49
const userinfo = os.userInfo();
50
log(dir, `Installing dependencies inside container ${process.env['VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME']}...`);
51
52
opts.cwd = root;
53
if (process.env['npm_config_arch'] === 'arm64') {
54
run('sudo', ['docker', 'run', '--rm', '--privileged', 'multiarch/qemu-user-static', '--reset', '-p', 'yes'], opts);
55
}
56
run('sudo', [
57
'docker', 'run',
58
'-e', 'GITHUB_TOKEN',
59
'-v', `${process.env['VSCODE_HOST_MOUNT']}:/root/vscode`,
60
'-v', `${process.env['VSCODE_HOST_MOUNT']}/.build/.netrc:/root/.netrc`,
61
'-v', `${process.env['VSCODE_NPMRC_PATH']}:/root/.npmrc`,
62
'-w', path.resolve('/root/vscode', dir),
63
process.env['VSCODE_REMOTE_DEPENDENCIES_CONTAINER_NAME'],
64
'sh', '-c', `\"chown -R root:root ${path.resolve('/root/vscode', dir)} && export PATH="/root/vscode/.build/nodejs-musl/usr/local/bin:$PATH" && npm i -g node-gyp-build && npm ci\"`
65
], opts);
66
run('sudo', ['chown', '-R', `${userinfo.uid}:${userinfo.gid}`, `${path.resolve(root, dir)}`], opts);
67
} else {
68
log(dir, 'Installing dependencies...');
69
run(npm, command.split(' '), opts);
70
}
71
removeParcelWatcherPrebuild(dir);
72
}
73
74
function setNpmrcConfig(dir: string, env: NodeJS.ProcessEnv) {
75
const npmrcPath = path.join(root, dir, '.npmrc');
76
const lines = fs.readFileSync(npmrcPath, 'utf8').split('\n');
77
78
for (const line of lines) {
79
const trimmedLine = line.trim();
80
if (trimmedLine && !trimmedLine.startsWith('#')) {
81
const [key, value] = trimmedLine.split('=');
82
env[`npm_config_${key}`] = value.replace(/^"(.*)"$/, '$1');
83
}
84
}
85
86
// Use our bundled node-gyp version
87
env['npm_config_node_gyp'] =
88
process.platform === 'win32'
89
? path.join(import.meta.dirname, 'gyp', 'node_modules', '.bin', 'node-gyp.cmd')
90
: path.join(import.meta.dirname, 'gyp', 'node_modules', '.bin', 'node-gyp');
91
92
// Force node-gyp to use process.config on macOS
93
// which defines clang variable as expected. Otherwise we
94
// run into compilation errors due to incorrect compiler
95
// configuration.
96
// NOTE: This means the process.config should contain
97
// the correct clang variable. So keep the version check
98
// in preinstall sync with this logic.
99
// Change was first introduced in https://github.com/nodejs/node/commit/6e0a2bb54c5bbeff0e9e33e1a0c683ed980a8a0f
100
if ((dir === 'remote' || dir === 'build') && process.platform === 'darwin') {
101
env['npm_config_force_process_config'] = 'true';
102
} else {
103
delete env['npm_config_force_process_config'];
104
}
105
106
if (dir === 'build') {
107
env['npm_config_target'] = process.versions.node;
108
env['npm_config_arch'] = process.arch;
109
}
110
}
111
112
function removeParcelWatcherPrebuild(dir: string) {
113
const parcelModuleFolder = path.join(root, dir, 'node_modules', '@parcel');
114
if (!fs.existsSync(parcelModuleFolder)) {
115
return;
116
}
117
118
const parcelModules = fs.readdirSync(parcelModuleFolder);
119
for (const moduleName of parcelModules) {
120
if (moduleName.startsWith('watcher-')) {
121
const modulePath = path.join(parcelModuleFolder, moduleName);
122
fs.rmSync(modulePath, { recursive: true, force: true });
123
log(dir, `Removed @parcel/watcher prebuilt module ${modulePath}`);
124
}
125
}
126
}
127
128
for (const dir of dirs) {
129
130
if (dir === '') {
131
removeParcelWatcherPrebuild(dir);
132
continue; // already executed in root
133
}
134
135
let opts: child_process.SpawnSyncOptions | undefined;
136
137
if (dir === 'build') {
138
opts = {
139
env: {
140
...process.env
141
},
142
};
143
if (process.env['CC']) { opts.env!['CC'] = 'gcc'; }
144
if (process.env['CXX']) { opts.env!['CXX'] = 'g++'; }
145
if (process.env['CXXFLAGS']) { opts.env!['CXXFLAGS'] = ''; }
146
if (process.env['LDFLAGS']) { opts.env!['LDFLAGS'] = ''; }
147
148
setNpmrcConfig('build', opts.env!);
149
npmInstall('build', opts);
150
continue;
151
}
152
153
if (/^(.build\/distro\/npm\/)?remote$/.test(dir)) {
154
// node modules used by vscode server
155
opts = {
156
env: {
157
...process.env
158
},
159
};
160
if (process.env['VSCODE_REMOTE_CC']) {
161
opts.env!['CC'] = process.env['VSCODE_REMOTE_CC'];
162
} else {
163
delete opts.env!['CC'];
164
}
165
if (process.env['VSCODE_REMOTE_CXX']) {
166
opts.env!['CXX'] = process.env['VSCODE_REMOTE_CXX'];
167
} else {
168
delete opts.env!['CXX'];
169
}
170
if (process.env['CXXFLAGS']) { delete opts.env!['CXXFLAGS']; }
171
if (process.env['CFLAGS']) { delete opts.env!['CFLAGS']; }
172
if (process.env['LDFLAGS']) { delete opts.env!['LDFLAGS']; }
173
if (process.env['VSCODE_REMOTE_CXXFLAGS']) { opts.env!['CXXFLAGS'] = process.env['VSCODE_REMOTE_CXXFLAGS']; }
174
if (process.env['VSCODE_REMOTE_LDFLAGS']) { opts.env!['LDFLAGS'] = process.env['VSCODE_REMOTE_LDFLAGS']; }
175
if (process.env['VSCODE_REMOTE_NODE_GYP']) { opts.env!['npm_config_node_gyp'] = process.env['VSCODE_REMOTE_NODE_GYP']; }
176
177
setNpmrcConfig('remote', opts.env!);
178
npmInstall(dir, opts);
179
continue;
180
}
181
182
npmInstall(dir, opts);
183
}
184
185
child_process.execSync('git config pull.rebase merges');
186
child_process.execSync('git config blame.ignoreRevsFile .git-blame-ignore-revs');
187
188