From a5e0db5ea838da175a510b7c9d5d79edb62d34cb Mon Sep 17 00:00:00 2001 From: Mark Lee Date: Tue, 26 Dec 2017 14:33:21 -0800 Subject: [PATCH] Fix ARM detection on armv7l Node Several versions of Node for armv7l incorrectly identify as `arm_version: '6'`. See: https://github.com/nodejs/node/issues/4531 and related --- package.json | 1 + targets.js | 21 ++++++++++++++++++--- test/targets.js | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index b88cfe95..2d1b6d91 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "eslint-plugin-standard": "^3.0.0", "nyc": "^11.0.0", "pkg-up": "^2.0.0", + "sinon": "^4.1.3", "tempy": "^0.2.1", "which": "^1.2.14" }, diff --git a/targets.js b/targets.js index b4d06e8b..6f50000d 100644 --- a/targets.js +++ b/targets.js @@ -1,5 +1,6 @@ 'use strict' +const execSync = require('child_process').execSync const semver = require('semver') const officialArchs = ['ia32', 'x64', 'armv7l', 'arm64'] @@ -73,9 +74,16 @@ function warnIfAllNotSpecified (opts, message) { } function hostArch () { - /* istanbul ignore if */ - if (process.arch === 'arm' && process.config.variables.arm_version === '7') { - return 'armv7l' + if (process.arch === 'arm') { + switch (process.config.variables.arm_version) { + case '6': + return module.exports.unameArch() + case '7': + return 'armv7l' + default: + const common = require('./common') + common.warning(`Could not determine specific ARM arch. Detected ARM version: ${JSON.stringify(process.config.variables.arm_version)}`) + } } return process.arch @@ -97,6 +105,13 @@ module.exports = { officialPlatforms: officialPlatforms, osModules: osModules, supported: supported, + /** + * Returns the arch name from the `uname` utility. + */ + unameArch: function unameArch () { + /* istanbul ignore next */ + return execSync('uname -m').toString().trim() + }, // Validates list of architectures or platforms. // Returns a normalized array if successful, or throws an Error. validateListFromOptions: function validateListFromOptions (opts, name) { diff --git a/test/targets.js b/test/targets.js index 02140e64..292b3f50 100644 --- a/test/targets.js +++ b/test/targets.js @@ -1,6 +1,7 @@ 'use strict' const config = require('./config.json') +const sinon = require('sinon') const targets = require('../targets') const test = require('ava') const util = require('./_util') @@ -51,6 +52,17 @@ test('validateListFromOptions does not take non-Array/String values', t => { delete targets.supported.digits }) +test('validateListFromOptions works for armv7l host and target arch', t => { + const sandbox = sinon.createSandbox() + + sandbox.stub(process, 'arch').value('arm') + sandbox.stub(process, 'config').value({variables: {arm_version: '7'}}) + + t.deepEqual(targets.validateListFromOptions({}, 'arch'), ['armv7l']) + + sandbox.restore() +}) + testMultiTarget('build for all available official targets', {all: true, electronVersion: '1.8.0'}, util.allPlatformArchCombosCount, 'Packages should be generated for all possible platforms') @@ -76,6 +88,40 @@ test('fails with invalid platform', util.invalidOptionTest({ platform: 'dos' })) +test('hostArch detects incorrectly configured armv7l Node', t => { + const sandbox = sinon.createSandbox() + + sandbox.stub(targets, 'unameArch').returns('armv7l') + sandbox.stub(process, 'arch').value('arm') + sandbox.stub(process, 'config').value({variables: {arm_version: '6'}}) + + t.is(targets.hostArch(), 'armv7l') + + sandbox.restore() +}) + +test('hostArch detects correctly configured armv7l Node', t => { + const sandbox = sinon.createSandbox() + + sandbox.stub(process, 'arch').value('arm') + sandbox.stub(process, 'config').value({variables: {arm_version: '7'}}) + + t.is(targets.hostArch(), 'armv7l') + + sandbox.restore() +}) + +test('hostArch cannot determine ARM version', t => { + const sandbox = sinon.createSandbox() + + sandbox.stub(process, 'arch').value('arm') + sandbox.stub(process, 'config').value({variables: {arm_version: '99'}}) + + t.is(targets.hostArch(), 'arm') + + sandbox.restore() +}) + testMultiTarget('invalid official combination', {arch: 'ia32', platform: 'darwin'}, 0, 'Package should not be generated for invalid official combination') testMultiTarget('platform=linux and arch=arm64 with a supported official Electron version', {arch: 'arm64', platform: 'linux', electronVersion: '1.8.0'}, 1, 'Package should be generated for arm64') testMultiTarget('platform=linux and arch=arm64 with an unsupported official Electron version', {arch: 'arm64', platform: 'linux'}, 0, 'Package should not be generated for arm64')