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