Skip to content

Commit 92abf0c

Browse files
committed
devops: show package names instead of missing libs on Ubuntu 18.04
This patch starts putting package names to install on Ubuntu instead of missing dependencies list. The mapping of library to package name is obtained using the following script: https://gist.github.com/aslushnikov/2766200430228c3700537292fccad064 References microsoft#2745
1 parent 056f0e2 commit 92abf0c

File tree

1 file changed

+124
-3
lines changed

1 file changed

+124
-3
lines changed

src/server/validateDependencies.ts

+124-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const accessAsync = util.promisify(fs.access.bind(fs));
2424
const checkExecutable = (filePath: string) => accessAsync(filePath, fs.constants.X_OK).then(() => true).catch(e => false);
2525
const statAsync = util.promisify(fs.stat.bind(fs));
2626
const readdirAsync = util.promisify(fs.readdir.bind(fs));
27+
const readFileAsync = util.promisify(fs.readFile.bind(fs));
2728

2829
export async function validateDependencies(browserPath: string, browser: BrowserDescriptor) {
2930
// We currently only support Linux.
@@ -34,15 +35,49 @@ export async function validateDependencies(browserPath: string, browser: Browser
3435
for (const directoryPath of directoryPaths)
3536
lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));
3637
const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath)));
37-
const missingDeps = new Set();
38+
const missingDeps : Set<string> = new Set();
3839
for (const deps of allMissingDeps) {
3940
for (const dep of deps)
4041
missingDeps.add(dep);
4142
}
4243
if (!missingDeps.size)
4344
return;
44-
const deps = [...missingDeps].sort().map(dep => ' ' + dep).join('\n');
45-
throw new Error('Host system is missing the following dependencies to run browser\n' + deps);
45+
// Check Ubuntu version.
46+
const missingPackages = new Set();
47+
const osRelease = await readFileAsync('/etc/os-release', 'utf8').catch(e => '');
48+
const [ubuntuName = '', ubuntuVersion = ''] = osRelease.trim().split('\n');
49+
if (ubuntuName.toLowerCase().includes('ubuntu') && ubuntuVersion.includes('18.04')) {
50+
// Translate missing dependencies to package names to install with apt.
51+
for (const missingDep of missingDeps) {
52+
const packageName = LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04[missingDep];
53+
if (packageName) {
54+
missingPackages.add(packageName);
55+
missingDeps.delete(missingDep);
56+
}
57+
}
58+
}
59+
60+
let missingPackagesMessage = ''
61+
if (missingPackages.size) {
62+
missingPackagesMessage = [
63+
` Install missing packages with:`,
64+
` apt-get install -y ${[...missingPackages].join('\\\n ')}`,
65+
``,
66+
``,
67+
].join('\n');
68+
}
69+
70+
let missingDependenciesMessage = '';
71+
if (missingDeps.size) {
72+
const header = missingPackages.size ? `Missing libraries we didn't find packages for:` : `Missing libraries are:`;
73+
missingDependenciesMessage = [
74+
` ${header}`,
75+
` ${[...missingDeps].join('\n ')}`,
76+
``,
77+
].join('\n');
78+
}
79+
80+
throw new Error('Host system is missing dependencies!\n\n' + missingPackagesMessage + missingDependenciesMessage);
4681
}
4782

4883
async function executablesOrSharedLibraries(directoryPath: string): Promise<string[]> {
@@ -86,3 +121,89 @@ function lddAsync(filePath: string): Promise<{stdout: string, stderr: string, co
86121
ldd.on('close', code => resolve({stdout, stderr, code}));
87122
});
88123
}
124+
125+
// This list is generated with https://gist.github.com/aslushnikov/2766200430228c3700537292fccad064
126+
const LIBRARY_TO_PACKAGE_NAME_UBUNTU_18_04: { [s: string]: string} = {
127+
'libEGL.so.1': 'libegl1',
128+
'libGL.so.1': 'libgl1',
129+
'libX11-xcb.so.1': 'libx11-xcb1',
130+
'libX11.so.6': 'libx11-6',
131+
'libXcomposite.so.1': 'libxcomposite1',
132+
'libXcursor.so.1': 'libxcursor1',
133+
'libXdamage.so.1': 'libxdamage1',
134+
'libXext.so.6': 'libxext6',
135+
'libXfixes.so.3': 'libxfixes3',
136+
'libXi.so.6': 'libxi6',
137+
'libXrandr.so.2': 'libxrandr2',
138+
'libXrender.so.1': 'libxrender1',
139+
'libXt.so.6': 'libxt6',
140+
'libXtst.so.6': 'libxtst6',
141+
'libasound.so.2': 'libasound2',
142+
'libatk-1.0.so.0': 'libatk1.0-0',
143+
'libatk-bridge-2.0.so.0': 'libatk-bridge2.0-0',
144+
'libatspi.so.0': 'libatspi2.0-0',
145+
'libbrotlidec.so.1': 'libbrotli1',
146+
'libcairo-gobject.so.2': 'libcairo-gobject2',
147+
'libcairo.so.2': 'libcairo2',
148+
'libcups.so.2': 'libcups2',
149+
'libdbus-1.so.3': 'libdbus-1-3',
150+
'libdbus-glib-1.so.2': 'libdbus-glib-1-2',
151+
'libdrm.so.2': 'libdrm2',
152+
'libenchant.so.1': 'libenchant1c2a',
153+
'libepoxy.so.0': 'libepoxy0',
154+
'libfontconfig.so.1': 'libfontconfig1',
155+
'libfreetype.so.6': 'libfreetype6',
156+
'libgbm.so.1': 'libgbm1',
157+
'libgdk-3.so.0': 'libgtk-3-0',
158+
'libgdk-x11-2.0.so.0': 'libgtk2.0-0',
159+
'libgdk_pixbuf-2.0.so.0': 'libgdk-pixbuf2.0-0',
160+
'libgio-2.0.so.0': 'libglib2.0-0',
161+
'libglib-2.0.so.0': 'libglib2.0-0',
162+
'libgmodule-2.0.so.0': 'libglib2.0-0',
163+
'libgobject-2.0.so.0': 'libglib2.0-0',
164+
'libgstapp-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
165+
'libgstaudio-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
166+
'libgstbase-1.0.so.0': 'libgstreamer1.0-0',
167+
'libgstcodecparsers-1.0.so.0': 'libgstreamer-plugins-bad1.0-0',
168+
'libgstfft-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
169+
'libgstgl-1.0.so.0': 'libgstreamer-gl1.0-0',
170+
'libgstpbutils-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
171+
'libgstreamer-1.0.so.0': 'libgstreamer1.0-0',
172+
'libgsttag-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
173+
'libgstvideo-1.0.so.0': 'libgstreamer-plugins-base1.0-0',
174+
'libgthread-2.0.so.0': 'libglib2.0-0',
175+
'libgtk-3.so.0': 'libgtk-3-0',
176+
'libgtk-x11-2.0.so.0': 'libgtk2.0-0',
177+
'libharfbuzz-icu.so.0': 'libharfbuzz-icu0',
178+
'libharfbuzz.so.0': 'libharfbuzz0b',
179+
'libhyphen.so.0': 'libhyphen0',
180+
'libicui18n.so.60': 'libicu60',
181+
'libicuuc.so.60': 'libicu60',
182+
'libjpeg.so.8': 'libjpeg-turbo8',
183+
'libnotify.so.4': 'libnotify4',
184+
'libnspr4.so': 'libnspr4',
185+
'libnss3.so': 'libnss3',
186+
'libnssutil3.so': 'libnss3',
187+
'libopenjp2.so.7': 'libopenjp2-7',
188+
'libopus.so.0': 'libopus0',
189+
'libpango-1.0.so.0': 'libpango-1.0-0',
190+
'libpangocairo-1.0.so.0': 'libpangocairo-1.0-0',
191+
'libpangoft2-1.0.so.0': 'libpangoft2-1.0-0',
192+
'libpng16.so.16': 'libpng16-16',
193+
'libsecret-1.so.0': 'libsecret-1-0',
194+
'libsmime3.so': 'libnss3',
195+
'libssl3.so': 'libnss3',
196+
'libwayland-client.so.0': 'libwayland-client0',
197+
'libwayland-egl.so.1': 'libwayland-egl1',
198+
'libwayland-server.so.0': 'libwayland-server0',
199+
'libwebp.so.6': 'libwebp6',
200+
'libwebpdemux.so.2': 'libwebpdemux2',
201+
'libwoff2dec.so.1.0.2': 'libwoff1',
202+
'libxcb-dri3.so.0': 'libxcb-dri3-0',
203+
'libxcb-shm.so.0': 'libxcb-shm0',
204+
'libxcb.so.1': 'libxcb1',
205+
'libxkbcommon.so.0': 'libxkbcommon0',
206+
'libxml2.so.2': 'libxml2',
207+
'libxslt.so.1': 'libxslt1.1',
208+
};
209+

0 commit comments

Comments
 (0)