deb包的control文件中添加Depends、Recommends字段,处理control的depends依赖包.

This commit is contained in:
chriswang521 2023-11-24 14:27:51 +08:00 committed by wangpenglong
parent 89ed698077
commit 95937a9a0d
12 changed files with 882 additions and 2 deletions

View File

@ -16,6 +16,9 @@ const task = require('./lib/task');
const packageJson = require('../package.json');
const product = require('../product.json');
const rpmDependenciesGenerator = require('./linux/rpm/dependencies-generator');
const debianDependenciesGenerator = require('./linux/debian/dependencies-generator');
const sysrootInstaller = require('./linux/debian/install-sysroot');
const debianRecommendedDependencies = require('./linux/debian/dep-lists').recommendedDeps;
const path = require('path');
const root = path.dirname(__dirname);
const commit = util.getVersion(root);
@ -91,12 +94,16 @@ function prepareDebPackage(arch) {
let size = 0;
const control = code.pipe(es.through(
function (f) { size += f.isDirectory() ? 4096 : f.contents.length; },
function () {
async function () {
const that = this;
const sysroot = await sysrootInstaller.getSysroot(debArch);
const dependencies = debianDependenciesGenerator.getDependencies('deb', binaryDir, product.applicationName, debArch, sysroot);
gulp.src('resources/linux/debian/control.template', { base: '.' })
.pipe(replace('@@NAME@@', product.applicationName))
.pipe(replace('@@VERSION@@', packageJson.IDEVersion + '-' + linuxPackageRevision))
.pipe(replace('@@ARCHITECTURE@@', debArch))
.pipe(replace('@@DEPENDS@@', dependencies.join(', ')))
.pipe(replace('@@RECOMMENDS@@', debianRecommendedDependencies.join(', ')))
.pipe(replace('@@INSTALLEDSIZE@@', Math.ceil(size / 1024)))
.pipe(rename('DEBIAN/control'))
.pipe(es.through(function (f) { that.emit('data', f); }, function () { that.emit('end'); }));

View File

@ -0,0 +1,87 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.generatePackageDeps = void 0;
const child_process_1 = require("child_process");
const fs_1 = require("fs");
const os_1 = require("os");
const path = require("path");
const manifests = require("../../../cgmanifest.json");
const dep_lists_1 = require("./dep-lists");
function generatePackageDeps(files, arch, sysroot) {
const dependencies = files.map(file => calculatePackageDeps(file, arch, sysroot));
const additionalDepsSet = new Set(dep_lists_1.additionalDeps);
dependencies.push(additionalDepsSet);
return dependencies;
}
exports.generatePackageDeps = generatePackageDeps;
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/calculate_package_deps.py.
function calculatePackageDeps(binaryPath, arch, sysroot) {
try {
if (!((0, fs_1.statSync)(binaryPath).mode & fs_1.constants.S_IXUSR)) {
throw new Error(`Binary ${binaryPath} needs to have an executable bit set.`);
}
}
catch (e) {
// The package might not exist. Don't re-throw the error here.
console.error('Tried to stat ' + binaryPath + ' but failed.');
}
// Get the Chromium dpkg-shlibdeps file.
const chromiumManifest = manifests.registrations.filter(registration => {
return registration.component.type === 'git' && registration.component.git.name === 'chromium';
});
const dpkgShlibdepsUrl = `https://raw.githubusercontent.com/chromium/chromium/${chromiumManifest[0].version}/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl`;
const dpkgShlibdepsScriptLocation = `${(0, os_1.tmpdir)()}/dpkg-shlibdeps.pl`;
const result = (0, child_process_1.spawnSync)('curl', [dpkgShlibdepsUrl, '-o', dpkgShlibdepsScriptLocation]);
if (result.status !== 0) {
throw new Error('Cannot retrieve dpkg-shlibdeps. Stderr:\n' + result.stderr);
}
const cmd = [dpkgShlibdepsScriptLocation, '--ignore-weak-undefined'];
switch (arch) {
case 'amd64':
cmd.push(`-l${sysroot}/usr/lib/x86_64-linux-gnu`, `-l${sysroot}/lib/x86_64-linux-gnu`);
break;
case 'armhf':
cmd.push(`-l${sysroot}/usr/lib/arm-linux-gnueabihf`, `-l${sysroot}/lib/arm-linux-gnueabihf`);
break;
case 'arm64':
cmd.push(`-l${sysroot}/usr/lib/aarch64-linux-gnu`, `-l${sysroot}/lib/aarch64-linux-gnu`);
break;
}
cmd.push(`-l${sysroot}/usr/lib`);
cmd.push('-O', '-e', path.resolve(binaryPath));
const dpkgShlibdepsResult = (0, child_process_1.spawnSync)('perl', cmd, { cwd: sysroot });
if (dpkgShlibdepsResult.status !== 0) {
throw new Error(`dpkg-shlibdeps failed with exit code ${dpkgShlibdepsResult.status}. stderr:\n${dpkgShlibdepsResult.stderr} `);
}
const shlibsDependsPrefix = 'shlibs:Depends=';
const requiresList = dpkgShlibdepsResult.stdout.toString('utf-8').trimEnd().split('\n');
let depsStr = '';
for (const line of requiresList) {
if (line.startsWith(shlibsDependsPrefix)) {
depsStr = line.substring(shlibsDependsPrefix.length);
}
}
// Refs https://chromium-review.googlesource.com/c/chromium/src/+/3572926
// Chromium depends on libgcc_s, is from the package libgcc1. However, in
// Bullseye, the package was renamed to libgcc-s1. To avoid adding a dep
// on the newer package, this hack skips the dep. This is safe because
// libgcc-s1 is a dependency of libc6. This hack can be removed once
// support for Debian Buster and Ubuntu Bionic are dropped.
//
// Remove kerberos native module related dependencies as the versions
// computed from sysroot will not satisfy the minimum supported distros
// Refs https://github.com/microsoft/vscode/issues/188881.
// TODO(deepak1556): remove this workaround in favor of computing the
// versions from build container for native modules.
const filteredDeps = depsStr.split(', ').filter(dependency => {
return !dependency.startsWith('libgcc-s1') &&
!dependency.startsWith('libgssapi-krb5-2') &&
!dependency.startsWith('libkrb5-3');
}).sort();
const requires = new Set(filteredDeps);
return requires;
}

View File

@ -0,0 +1,92 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { spawnSync } from 'child_process';
import { constants, statSync } from 'fs';
import { tmpdir } from 'os';
import path = require('path');
import * as manifests from '../../../cgmanifest.json';
import { additionalDeps } from './dep-lists';
import { DebianArchString } from './types';
export function generatePackageDeps(files: string[], arch: DebianArchString, sysroot: string): Set<string>[] {
const dependencies: Set<string>[] = files.map(file => calculatePackageDeps(file, arch, sysroot));
const additionalDepsSet = new Set(additionalDeps);
dependencies.push(additionalDepsSet);
return dependencies;
}
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/calculate_package_deps.py.
function calculatePackageDeps(binaryPath: string, arch: DebianArchString, sysroot: string): Set<string> {
try {
if (!(statSync(binaryPath).mode & constants.S_IXUSR)) {
throw new Error(`Binary ${binaryPath} needs to have an executable bit set.`);
}
} catch (e) {
// The package might not exist. Don't re-throw the error here.
console.error('Tried to stat ' + binaryPath + ' but failed.');
}
// Get the Chromium dpkg-shlibdeps file.
const chromiumManifest = manifests.registrations.filter(registration => {
return registration.component.type === 'git' && registration.component.git!.name === 'chromium';
});
const dpkgShlibdepsUrl = `https://raw.githubusercontent.com/chromium/chromium/${chromiumManifest[0].version}/third_party/dpkg-shlibdeps/dpkg-shlibdeps.pl`;
const dpkgShlibdepsScriptLocation = `${tmpdir()}/dpkg-shlibdeps.pl`;
const result = spawnSync('curl', [dpkgShlibdepsUrl, '-o', dpkgShlibdepsScriptLocation]);
if (result.status !== 0) {
throw new Error('Cannot retrieve dpkg-shlibdeps. Stderr:\n' + result.stderr);
}
const cmd = [dpkgShlibdepsScriptLocation, '--ignore-weak-undefined'];
switch (arch) {
case 'amd64':
cmd.push(`-l${sysroot}/usr/lib/x86_64-linux-gnu`,
`-l${sysroot}/lib/x86_64-linux-gnu`);
break;
case 'armhf':
cmd.push(`-l${sysroot}/usr/lib/arm-linux-gnueabihf`,
`-l${sysroot}/lib/arm-linux-gnueabihf`);
break;
case 'arm64':
cmd.push(`-l${sysroot}/usr/lib/aarch64-linux-gnu`,
`-l${sysroot}/lib/aarch64-linux-gnu`);
break;
}
cmd.push(`-l${sysroot}/usr/lib`);
cmd.push('-O', '-e', path.resolve(binaryPath));
const dpkgShlibdepsResult = spawnSync('perl', cmd, { cwd: sysroot });
if (dpkgShlibdepsResult.status !== 0) {
throw new Error(`dpkg-shlibdeps failed with exit code ${dpkgShlibdepsResult.status}. stderr:\n${dpkgShlibdepsResult.stderr} `);
}
const shlibsDependsPrefix = 'shlibs:Depends=';
const requiresList = dpkgShlibdepsResult.stdout.toString('utf-8').trimEnd().split('\n');
let depsStr = '';
for (const line of requiresList) {
if (line.startsWith(shlibsDependsPrefix)) {
depsStr = line.substring(shlibsDependsPrefix.length);
}
}
// Refs https://chromium-review.googlesource.com/c/chromium/src/+/3572926
// Chromium depends on libgcc_s, is from the package libgcc1. However, in
// Bullseye, the package was renamed to libgcc-s1. To avoid adding a dep
// on the newer package, this hack skips the dep. This is safe because
// libgcc-s1 is a dependency of libc6. This hack can be removed once
// support for Debian Buster and Ubuntu Bionic are dropped.
//
// Remove kerberos native module related dependencies as the versions
// computed from sysroot will not satisfy the minimum supported distros
// Refs https://github.com/microsoft/vscode/issues/188881.
// TODO(deepak1556): remove this workaround in favor of computing the
// versions from build container for native modules.
const filteredDeps = depsStr.split(', ').filter(dependency => {
return !dependency.startsWith('libgcc-s1') &&
!dependency.startsWith('libgssapi-krb5-2') &&
!dependency.startsWith('libkrb5-3');
}).sort();
const requires = new Set(filteredDeps);
return requires;
}

View File

@ -0,0 +1,146 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.referenceGeneratedDepsByArch = exports.recommendedDeps = exports.additionalDeps = void 0;
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/additional_deps
// Additional dependencies not in the dpkg-shlibdeps output.
exports.additionalDeps = [
'ca-certificates', // Make sure users have SSL certificates.
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libnss3 (>= 3.26)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', // For Breakpad crash reports.
'xdg-utils (>= 1.0.2)', // OS integration
];
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/manual_recommends
// Dependencies that we can only recommend
// for now since some of the older distros don't support them.
exports.recommendedDeps = [
'libvulkan1' // Move to additionalDeps once support for Trusty and Jessie are dropped.
];
exports.referenceGeneratedDepsByArch = {
'amd64': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.14)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.28)',
'libc6 (>= 2.29)',
'libc6 (>= 2.4)',
'libcairo2 (>= 1.6.0)',
'libcups2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.5.12)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.12.0)',
'libglib2.0-0 (>= 2.37.3)',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 9)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1 (>= 1:1.1.0)',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
],
'armhf': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.15)',
'libc6 (>= 2.16)',
'libc6 (>= 2.17)',
'libc6 (>= 2.4)',
'libc6 (>= 2.8)',
'libc6 (>= 2.9)',
'libcairo2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.5.12)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.37.3)',
'libgssapi-krb5-2',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libkrb5-3',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
],
'arm64': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.17)',
'libcairo2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.0.2)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.37.3)',
'libgssapi-krb5-2',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libkrb5-3',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
]
};

View File

@ -0,0 +1,149 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/additional_deps
// Additional dependencies not in the dpkg-shlibdeps output.
export const additionalDeps = [
'ca-certificates', // Make sure users have SSL certificates.
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libnss3 (>= 3.26)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3', // For Breakpad crash reports.
'xdg-utils (>= 1.0.2)', // OS integration
];
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/debian/manual_recommends
// Dependencies that we can only recommend
// for now since some of the older distros don't support them.
export const recommendedDeps = [
'libvulkan1' // Move to additionalDeps once support for Trusty and Jessie are dropped.
];
export const referenceGeneratedDepsByArch = {
'amd64': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.14)',
'libc6 (>= 2.15)',
'libc6 (>= 2.17)',
'libc6 (>= 2.28)',
'libc6 (>= 2.29)',
'libc6 (>= 2.4)',
'libcairo2 (>= 1.6.0)',
'libcups2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.5.12)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.12.0)',
'libglib2.0-0 (>= 2.37.3)',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 9)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1 (>= 1:1.1.0)',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
],
'armhf': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.15)',
'libc6 (>= 2.16)',
'libc6 (>= 2.17)',
'libc6 (>= 2.4)',
'libc6 (>= 2.8)',
'libc6 (>= 2.9)',
'libcairo2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.5.12)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.37.3)',
'libgssapi-krb5-2',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libkrb5-3',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 6)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
],
'arm64': [
'ca-certificates',
'libasound2 (>= 1.0.17)',
'libatk-bridge2.0-0 (>= 2.5.3)',
'libatk1.0-0 (>= 2.2.0)',
'libatspi2.0-0 (>= 2.9.90)',
'libc6 (>= 2.17)',
'libc6 (>= 2.28)',
'libc6 (>= 2.29)',
'libcairo2 (>= 1.6.0)',
'libcups2 (>= 1.6.0)',
'libcurl3-gnutls | libcurl3-nss | libcurl4 | libcurl3',
'libdbus-1-3 (>= 1.0.2)',
'libdrm2 (>= 2.4.75)',
'libexpat1 (>= 2.0.1)',
'libgbm1 (>= 17.1.0~rc2)',
'libglib2.0-0 (>= 2.12.0)',
'libglib2.0-0 (>= 2.37.3)',
'libgtk-3-0 (>= 3.9.10)',
'libgtk-3-0 (>= 3.9.10) | libgtk-4-1',
'libnspr4 (>= 2:4.9-2~)',
'libnss3 (>= 2:3.30)',
'libnss3 (>= 3.26)',
'libpango-1.0-0 (>= 1.14.0)',
'libsecret-1-0 (>= 0.18)',
'libstdc++6 (>= 5)',
'libstdc++6 (>= 5.2)',
'libstdc++6 (>= 9)',
'libx11-6',
'libx11-6 (>= 2:1.4.99.1)',
'libxcb1 (>= 1.9.2)',
'libxcomposite1 (>= 1:0.4.4-1)',
'libxdamage1 (>= 1:1.1)',
'libxext6',
'libxfixes3',
'libxkbcommon0 (>= 0.4.1)',
'libxkbfile1 (>= 1:1.1.0)',
'libxrandr2',
'xdg-utils (>= 1.0.2)'
]
};

View File

@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDependencies = void 0;
const child_process_1 = require("child_process");
const path = require("path");
const calculate_deps_1 = require("./calculate-deps");
const dep_lists_1 = require("./dep-lists");
const types_1 = require("./types");
// A flag that can easily be toggled.
// Make sure to compile the build directory after toggling the value.
// If false, we warn about new dependencies if they show up
// while running the prepare package tasks for a release.
// If true, we fail the build if there are new dependencies found during that task.
// The reference dependencies, which one has to update when the new dependencies
// are valid, are in dep-lists.ts
const FAIL_BUILD_FOR_NEW_DEPENDENCIES = true;
// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/114.0.5735.199:chrome/installer/linux/BUILD.gn;l=64-80
// and the Linux Archive build
// Shared library dependencies that we already bundle.
const bundledDeps = [
'libEGL.so',
'libGLESv2.so',
'libvulkan.so.1',
'libvk_swiftshader.so',
'libffmpeg.so'
];
function getDependencies(packageType, buildDir, applicationName, arch, sysroot) {
if (packageType === 'deb') {
if (!(0, types_1.isDebianArchString)(arch)) {
throw new Error('Invalid Debian arch string ' + arch);
}
if (!sysroot) {
throw new Error('Missing sysroot parameter');
}
}
// Get the files for which we want to find dependencies.
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
const findResult = (0, child_process_1.spawnSync)('find', [nativeModulesPath, '-name', '*.node']);
if (findResult.status) {
console.error('Error finding files:');
console.error(findResult.stderr.toString());
return [];
}
const files = findResult.stdout.toString().trimEnd().split('\n');
const appPath = path.join(buildDir, applicationName);
files.push(appPath);
// Add chrome sandbox and crashpad handler.
files.push(path.join(buildDir, 'chrome-sandbox'));
files.push(path.join(buildDir, 'chrome_crashpad_handler'));
// Generate the dependencies.
const dependencies = (0, calculate_deps_1.generatePackageDeps)(files, arch, sysroot);
// Merge all the dependencies.
const mergedDependencies = mergePackageDeps(dependencies);
// Exclude bundled dependencies and sort
const sortedDependencies = Array.from(mergedDependencies).filter(dependency => {
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
}).sort();
const referenceGeneratedDeps = dep_lists_1.referenceGeneratedDepsByArch[arch];
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
const failMessage = 'The dependencies list has changed.'
+ '\nOld:\n' + referenceGeneratedDeps.join('\n')
+ '\nNew:\n' + sortedDependencies.join('\n');
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
throw new Error(failMessage);
}
else {
console.warn(failMessage);
}
}
return sortedDependencies;
}
exports.getDependencies = getDependencies;
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/rpm/merge_package_deps.py.
function mergePackageDeps(inputDeps) {
const requires = new Set();
for (const depSet of inputDeps) {
for (const dep of depSet) {
const trimmedDependency = dep.trim();
if (trimmedDependency.length && !trimmedDependency.startsWith('#')) {
requires.add(trimmedDependency);
}
}
}
return requires;
}

View File

@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { spawnSync } from 'child_process';
import path = require('path');
import { generatePackageDeps as generatePackageDepsDebian } from './calculate-deps';
import { referenceGeneratedDepsByArch as debianGeneratedDeps } from './dep-lists';
import { DebianArchString, isDebianArchString } from './types';
// A flag that can easily be toggled.
// Make sure to compile the build directory after toggling the value.
// If false, we warn about new dependencies if they show up
// while running the prepare package tasks for a release.
// If true, we fail the build if there are new dependencies found during that task.
// The reference dependencies, which one has to update when the new dependencies
// are valid, are in dep-lists.ts
const FAIL_BUILD_FOR_NEW_DEPENDENCIES: boolean = true;
// Based on https://source.chromium.org/chromium/chromium/src/+/refs/tags/114.0.5735.199:chrome/installer/linux/BUILD.gn;l=64-80
// and the Linux Archive build
// Shared library dependencies that we already bundle.
const bundledDeps = [
'libEGL.so',
'libGLESv2.so',
'libvulkan.so.1',
'libvk_swiftshader.so',
'libffmpeg.so'
];
export function getDependencies(packageType: 'deb' | 'rpm', buildDir: string, applicationName: string, arch: string, sysroot?: string): string[] {
if (packageType === 'deb') {
if (!isDebianArchString(arch)) {
throw new Error('Invalid Debian arch string ' + arch);
}
if (!sysroot) {
throw new Error('Missing sysroot parameter');
}
}
// Get the files for which we want to find dependencies.
const nativeModulesPath = path.join(buildDir, 'resources', 'app', 'node_modules.asar.unpacked');
const findResult = spawnSync('find', [nativeModulesPath, '-name', '*.node']);
if (findResult.status) {
console.error('Error finding files:');
console.error(findResult.stderr.toString());
return [];
}
const files = findResult.stdout.toString().trimEnd().split('\n');
const appPath = path.join(buildDir, applicationName);
files.push(appPath);
// Add chrome sandbox and crashpad handler.
files.push(path.join(buildDir, 'chrome-sandbox'));
files.push(path.join(buildDir, 'chrome_crashpad_handler'));
// Generate the dependencies.
const dependencies = generatePackageDepsDebian(files, arch as DebianArchString, sysroot!);
// Merge all the dependencies.
const mergedDependencies = mergePackageDeps(dependencies);
// Exclude bundled dependencies and sort
const sortedDependencies: string[] = Array.from(mergedDependencies).filter(dependency => {
return !bundledDeps.some(bundledDep => dependency.startsWith(bundledDep));
}).sort();
const referenceGeneratedDeps = debianGeneratedDeps[arch as DebianArchString];
if (JSON.stringify(sortedDependencies) !== JSON.stringify(referenceGeneratedDeps)) {
const failMessage = 'The dependencies list has changed.'
+ '\nOld:\n' + referenceGeneratedDeps.join('\n')
+ '\nNew:\n' + sortedDependencies.join('\n');
if (FAIL_BUILD_FOR_NEW_DEPENDENCIES) {
throw new Error(failMessage);
} else {
console.warn(failMessage);
}
}
return sortedDependencies;
}
// Based on https://source.chromium.org/chromium/chromium/src/+/main:chrome/installer/linux/rpm/merge_package_deps.py.
function mergePackageDeps(inputDeps: Set<string>[]): Set<string> {
const requires = new Set<string>();
for (const depSet of inputDeps) {
for (const dep of depSet) {
const trimmedDependency = dep.trim();
if (trimmedDependency.length && !trimmedDependency.startsWith('#')) {
requires.add(trimmedDependency);
}
}
}
return requires;
}

View File

@ -0,0 +1,89 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSysroot = void 0;
const child_process_1 = require("child_process");
const crypto_1 = require("crypto");
const os_1 = require("os");
const fs = require("fs");
const https = require("https");
const path = require("path");
const util = require("../../lib/util");
// Based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/install-sysroot.py.
const URL_PREFIX = 'https://msftelectron.blob.core.windows.net';
const URL_PATH = 'sysroots/toolchain';
function getSha(filename) {
const hash = (0, crypto_1.createHash)('sha1');
// Read file 1 MB at a time
const fd = fs.openSync(filename, 'r');
const buffer = Buffer.alloc(1024 * 1024);
let position = 0;
let bytesRead = 0;
while ((bytesRead = fs.readSync(fd, buffer, 0, buffer.length, position)) === buffer.length) {
hash.update(buffer);
position += bytesRead;
}
hash.update(buffer.slice(0, bytesRead));
return hash.digest('hex');
}
async function getSysroot(arch) {
const sysrootJSONUrl = `https://raw.githubusercontent.com/electron/electron/v${util.getElectronVersion()}/script/sysroots.json`;
const sysrootDictLocation = `${(0, os_1.tmpdir)()}/sysroots.json`;
const result = (0, child_process_1.spawnSync)('curl', [sysrootJSONUrl, '-o', sysrootDictLocation]);
if (result.status !== 0) {
throw new Error('Cannot retrieve sysroots.json. Stderr:\n' + result.stderr);
}
const sysrootInfo = require(sysrootDictLocation);
const sysrootArch = arch === 'armhf' ? 'bullseye_arm' : `bullseye_${arch}`;
const sysrootDict = sysrootInfo[sysrootArch];
const tarballFilename = sysrootDict['Tarball'];
const tarballSha = sysrootDict['Sha1Sum'];
const sysroot = path.join((0, os_1.tmpdir)(), sysrootDict['SysrootDir']);
const url = [URL_PREFIX, URL_PATH, tarballSha, tarballFilename].join('/');
const stamp = path.join(sysroot, '.stamp');
if (fs.existsSync(stamp) && fs.readFileSync(stamp).toString() === url) {
return sysroot;
}
console.log(`Installing Debian ${arch} root image: ${sysroot}`);
fs.rmSync(sysroot, { recursive: true, force: true });
fs.mkdirSync(sysroot);
const tarball = path.join(sysroot, tarballFilename);
console.log(`Downloading ${url}`);
let downloadSuccess = false;
for (let i = 0; i < 3 && !downloadSuccess; i++) {
fs.writeFileSync(tarball, '');
await new Promise((c) => {
https.get(url, (res) => {
res.on('data', (chunk) => {
fs.appendFileSync(tarball, chunk);
});
res.on('end', () => {
downloadSuccess = true;
c();
});
}).on('error', (err) => {
console.error('Encountered an error during the download attempt: ' + err.message);
c();
});
});
}
if (!downloadSuccess) {
fs.rmSync(tarball);
throw new Error('Failed to download ' + url);
}
const sha = getSha(tarball);
if (sha !== tarballSha) {
throw new Error(`Tarball sha1sum is wrong. Expected ${tarballSha}, actual ${sha}`);
}
const proc = (0, child_process_1.spawnSync)('tar', ['xf', tarball, '-C', sysroot]);
if (proc.status) {
throw new Error('Tarball extraction failed with code ' + proc.status);
}
fs.rmSync(tarball);
fs.writeFileSync(stamp, url);
return sysroot;
}
exports.getSysroot = getSysroot;

View File

@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { spawnSync } from 'child_process';
import { createHash } from 'crypto';
import { tmpdir } from 'os';
import * as fs from 'fs';
import * as https from 'https';
import * as path from 'path';
import { DebianArchString } from './types';
import * as util from '../../lib/util';
// Based on https://source.chromium.org/chromium/chromium/src/+/main:build/linux/sysroot_scripts/install-sysroot.py.
const URL_PREFIX = 'https://msftelectron.blob.core.windows.net';
const URL_PATH = 'sysroots/toolchain';
function getSha(filename: fs.PathLike): string {
const hash = createHash('sha1');
// Read file 1 MB at a time
const fd = fs.openSync(filename, 'r');
const buffer = Buffer.alloc(1024 * 1024);
let position = 0;
let bytesRead = 0;
while ((bytesRead = fs.readSync(fd, buffer, 0, buffer.length, position)) === buffer.length) {
hash.update(buffer);
position += bytesRead;
}
hash.update(buffer.slice(0, bytesRead));
return hash.digest('hex');
}
type SysrootDictEntry = {
Sha1Sum: string;
SysrootDir: string;
Tarball: string;
};
export async function getSysroot(arch: DebianArchString): Promise<string> {
const sysrootJSONUrl = `https://raw.githubusercontent.com/electron/electron/v${util.getElectronVersion()}/script/sysroots.json`;
const sysrootDictLocation = `${tmpdir()}/sysroots.json`;
const result = spawnSync('curl', [sysrootJSONUrl, '-o', sysrootDictLocation]);
if (result.status !== 0) {
throw new Error('Cannot retrieve sysroots.json. Stderr:\n' + result.stderr);
}
const sysrootInfo = require(sysrootDictLocation);
const sysrootArch = arch === 'armhf' ? 'bullseye_arm' : `bullseye_${arch}`;
const sysrootDict: SysrootDictEntry = sysrootInfo[sysrootArch];
const tarballFilename = sysrootDict['Tarball'];
const tarballSha = sysrootDict['Sha1Sum'];
const sysroot = path.join(tmpdir(), sysrootDict['SysrootDir']);
const url = [URL_PREFIX, URL_PATH, tarballSha, tarballFilename].join('/');
const stamp = path.join(sysroot, '.stamp');
if (fs.existsSync(stamp) && fs.readFileSync(stamp).toString() === url) {
return sysroot;
}
console.log(`Installing Debian ${arch} root image: ${sysroot}`);
fs.rmSync(sysroot, { recursive: true, force: true });
fs.mkdirSync(sysroot);
const tarball = path.join(sysroot, tarballFilename);
console.log(`Downloading ${url}`);
let downloadSuccess = false;
for (let i = 0; i < 3 && !downloadSuccess; i++) {
fs.writeFileSync(tarball, '');
await new Promise<void>((c) => {
https.get(url, (res) => {
res.on('data', (chunk) => {
fs.appendFileSync(tarball, chunk);
});
res.on('end', () => {
downloadSuccess = true;
c();
});
}).on('error', (err) => {
console.error('Encountered an error during the download attempt: ' + err.message);
c();
});
});
}
if (!downloadSuccess) {
fs.rmSync(tarball);
throw new Error('Failed to download ' + url);
}
const sha = getSha(tarball);
if (sha !== tarballSha) {
throw new Error(`Tarball sha1sum is wrong. Expected ${tarballSha}, actual ${sha}`);
}
const proc = spawnSync('tar', ['xf', tarball, '-C', sysroot]);
if (proc.status) {
throw new Error('Tarball extraction failed with code ' + proc.status);
}
fs.rmSync(tarball);
fs.writeFileSync(stamp, url);
return sysroot;
}

View File

@ -0,0 +1,11 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isDebianArchString = void 0;
function isDebianArchString(s) {
return ['amd64', 'armhf', 'arm64'].includes(s);
}
exports.isDebianArchString = isDebianArchString;

View File

@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export type DebianArchString = 'amd64' | 'armhf' | 'arm64';
export function isDebianArchString(s: string): s is DebianArchString {
return ['amd64', 'armhf', 'arm64'].includes(s);
}

View File

@ -1,7 +1,8 @@
Package: @@NAME@@
Version: @@VERSION@@
Section: devel
Depends: libnss3 (>= 2:3.26), gnupg, apt, libxkbfile1, libsecret-1-0, libgtk-3-0 (>= 3.10.0), libxss1, libgbm1
Depends: @@DEPENDS@@
Recommends: @@RECOMMENDS@@
Priority: optional
Architecture: @@ARCHITECTURE@@
Maintainer: KylinIdeTeam https://gitee.com/openkylin/kylin-code/contributors?ref=master