mirror of
https://github.com/lovell/sharp.git
synced 2025-07-13 12:20:13 +02:00
Verify platform of vendor binaries at install and run time
This commit is contained in:
parent
57946ed672
commit
7b6c80327e
50
binding.js
50
binding.js
@ -10,24 +10,15 @@ const semver = require('semver');
|
||||
const tar = require('tar');
|
||||
const detectLibc = require('detect-libc');
|
||||
|
||||
const platform = require('./lib/platform');
|
||||
|
||||
// Use NPM-provided environment variable where available, falling back to require-based method for Electron
|
||||
const minimumLibvipsVersion = process.env.npm_package_config_libvips || require('./package.json').config.libvips;
|
||||
|
||||
const distBaseUrl = process.env.SHARP_DIST_BASE_URL || `https://github.com/lovell/sharp-libvips/releases/download/v${minimumLibvipsVersion}/`;
|
||||
|
||||
const platform = process.env.npm_config_platform || process.platform;
|
||||
|
||||
const arch = process.env.npm_config_arch || process.arch;
|
||||
|
||||
// -- Helpers
|
||||
|
||||
// Does this file exist?
|
||||
const isFile = function (file) {
|
||||
try {
|
||||
return fs.statSync(file).isFile();
|
||||
} catch (err) {}
|
||||
};
|
||||
|
||||
const unpack = function (tarPath, done) {
|
||||
const vendorPath = path.join(__dirname, 'vendor');
|
||||
fs.mkdirSync(vendorPath);
|
||||
@ -41,33 +32,29 @@ const unpack = function (tarPath, done) {
|
||||
.catch(error);
|
||||
};
|
||||
|
||||
const platformId = function () {
|
||||
const platformId = [platform];
|
||||
if (arch === 'arm' || arch === 'armhf' || arch === 'arm64') {
|
||||
const armVersion = (arch === 'arm64') ? '8' : process.env.npm_config_armv || process.config.variables.arm_version || '6';
|
||||
platformId.push('armv' + armVersion);
|
||||
} else {
|
||||
platformId.push(arch);
|
||||
}
|
||||
return platformId.join('-');
|
||||
};
|
||||
|
||||
// Error
|
||||
const error = function (msg) {
|
||||
if (msg instanceof Error) {
|
||||
msg = msg.message;
|
||||
}
|
||||
process.stderr.write('ERROR: ' + msg + '\n');
|
||||
process.stderr.write(`sharp: ${msg}\n`);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
// -- Binary downloaders
|
||||
|
||||
module.exports.download_vips = function () {
|
||||
// Has vips been installed locally?
|
||||
const vipsHeaderPath = path.join(__dirname, 'vendor', 'include', 'vips', 'vips.h');
|
||||
if (!isFile(vipsHeaderPath)) {
|
||||
// Check for existing vendored binaries and verify platform matches
|
||||
const currentPlatformId = platform();
|
||||
try {
|
||||
const vendorPlatformId = require(path.join(__dirname, 'vendor', 'platform.json'));
|
||||
if (currentPlatformId === vendorPlatformId) {
|
||||
return;
|
||||
} else {
|
||||
error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm install'.`);
|
||||
}
|
||||
} catch (err) {}
|
||||
// Ensure Intel 64-bit or ARM
|
||||
const arch = process.env.npm_config_arch || process.arch;
|
||||
if (arch === 'ia32') {
|
||||
error('Intel Architecture 32-bit systems require manual installation of libvips - please see http://sharp.dimens.io/page/install');
|
||||
}
|
||||
@ -80,9 +67,9 @@ module.exports.download_vips = function () {
|
||||
error(`Use with glibc version ${detectLibc.version} requires manual installation of libvips - please see http://sharp.dimens.io/page/install`);
|
||||
}
|
||||
// Arch/platform-specific .tar.gz
|
||||
const tarFilename = ['libvips', minimumLibvipsVersion, platformId()].join('-') + '.tar.gz';
|
||||
const tarFilename = ['libvips', minimumLibvipsVersion, currentPlatformId].join('-') + '.tar.gz';
|
||||
// Download to per-process temporary file
|
||||
const tarPathTemp = path.join(os.tmpdir(), process.pid + '-' + tarFilename);
|
||||
const tarPathTemp = path.join(os.tmpdir(), `${process.pid}-${tarFilename}`);
|
||||
const tmpFile = fs.createWriteStream(tarPathTemp).on('finish', function () {
|
||||
unpack(tarPathTemp, function () {
|
||||
// Attempt to remove temporary file
|
||||
@ -100,14 +87,13 @@ module.exports.download_vips = function () {
|
||||
};
|
||||
simpleGet(simpleGetOpt, function (err, response) {
|
||||
if (err) {
|
||||
error('Download of ' + url + ' failed: ' + err.message);
|
||||
error(`${url} download failed: ${err.message}`);
|
||||
}
|
||||
if (response.statusCode !== 200) {
|
||||
error(url + ' status code ' + response.statusCode);
|
||||
error(`${url} download failed: status ${response.statusCode}`);
|
||||
}
|
||||
response.pipe(tmpFile);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.use_global_vips = function () {
|
||||
|
@ -6,8 +6,24 @@ const stream = require('stream');
|
||||
const events = require('events');
|
||||
const semver = require('semver');
|
||||
const is = require('./is');
|
||||
const platform = require('./platform');
|
||||
const sharp = require('../build/Release/sharp.node');
|
||||
|
||||
// Vendor platform
|
||||
(function () {
|
||||
let vendorPlatformId;
|
||||
try {
|
||||
vendorPlatformId = require('../vendor/platform.json');
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
const currentPlatformId = platform();
|
||||
/* istanbul ignore if */
|
||||
if (currentPlatformId !== vendorPlatformId) {
|
||||
throw new Error(`'${vendorPlatformId}' binaries cannot be used on the '${currentPlatformId}' platform. Please remove the 'node_modules/sharp/vendor' directory and run 'npm rebuild'.`);
|
||||
}
|
||||
})();
|
||||
|
||||
// Versioning
|
||||
let versions = {
|
||||
vips: sharp.libvipsVersion()
|
||||
@ -21,7 +37,7 @@ let versions = {
|
||||
}
|
||||
// Include versions of dependencies, if present
|
||||
try {
|
||||
versions = require('../vendor/lib/versions.json');
|
||||
versions = require('../vendor/versions.json');
|
||||
} catch (err) {}
|
||||
})();
|
||||
|
||||
|
15
lib/platform.js
Normal file
15
lib/platform.js
Normal file
@ -0,0 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function () {
|
||||
const arch = process.env.npm_config_arch || process.arch;
|
||||
const platform = process.env.npm_config_platform || process.platform;
|
||||
|
||||
const platformId = [platform];
|
||||
if (arch === 'arm' || arch === 'armhf' || arch === 'arm64') {
|
||||
const armVersion = (arch === 'arm64') ? '8' : process.env.npm_config_armv || process.config.variables.arm_version || '6';
|
||||
platformId.push(`armv${armVersion}`);
|
||||
} else {
|
||||
platformId.push(arch);
|
||||
}
|
||||
return platformId.join('-');
|
||||
};
|
47
test/unit/platform.js
Normal file
47
test/unit/platform.js
Normal file
@ -0,0 +1,47 @@
|
||||
'use strict';
|
||||
|
||||
const assert = require('assert');
|
||||
const platform = require('../../lib/platform');
|
||||
|
||||
describe('Platform-detection', function () {
|
||||
it('Can override arch with npm_config_arch', function () {
|
||||
process.env.npm_config_arch = 'test';
|
||||
assert.strictEqual('test', platform().split('-')[1]);
|
||||
delete process.env.npm_config_arch;
|
||||
});
|
||||
|
||||
it('Can override platform with npm_config_platform', function () {
|
||||
process.env.npm_config_platform = 'test';
|
||||
assert.strictEqual('test', platform().split('-')[0]);
|
||||
delete process.env.npm_config_platform;
|
||||
});
|
||||
|
||||
it('Can override ARM version via npm_config_armv', function () {
|
||||
process.env.npm_config_arch = 'arm';
|
||||
process.env.npm_config_armv = 'test';
|
||||
assert.strictEqual('armvtest', platform().split('-')[1]);
|
||||
delete process.env.npm_config_armv;
|
||||
delete process.env.npm_config_arch;
|
||||
});
|
||||
|
||||
it('Can detect ARM version via process.config', function () {
|
||||
process.env.npm_config_arch = 'armhf';
|
||||
const armVersion = process.config.variables.arm_version;
|
||||
process.config.variables.arm_version = 'test';
|
||||
assert.strictEqual('armvtest', platform().split('-')[1]);
|
||||
process.config.variables.arm_version = armVersion;
|
||||
delete process.env.npm_config_arch;
|
||||
});
|
||||
|
||||
it('Defaults to ARMv6 for 32-bit', function () {
|
||||
process.env.npm_config_arch = 'arm';
|
||||
assert.strictEqual('armv6', platform().split('-')[1]);
|
||||
delete process.env.npm_config_arch;
|
||||
});
|
||||
|
||||
it('Defaults to ARMv8 for 64-bit', function () {
|
||||
process.env.npm_config_arch = 'arm64';
|
||||
assert.strictEqual('armv8', platform().split('-')[1]);
|
||||
delete process.env.npm_config_arch;
|
||||
});
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user