mirror of
https://github.com/balena-io/balena-cli.git
synced 2025-02-20 09:26:42 +00:00
Merge qemu-ts.ts and qemu.ts files
This commit is contained in:
parent
52bece7f17
commit
cbcd7694a9
@ -232,7 +232,7 @@ export function buildProject(
|
||||
checkBuildSecretsRequirements,
|
||||
makeBuildTasks,
|
||||
} = require('./compose_ts');
|
||||
const qemu = require('./qemu-ts');
|
||||
const qemu = require('./qemu');
|
||||
const { toPosixPath } = builder.PathUtils;
|
||||
|
||||
logger.logInfo(`Building for ${arch}/${deviceType}`);
|
||||
|
@ -1,84 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2019 Balena Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { stripIndent } from 'common-tags';
|
||||
import Dockerode = require('dockerode');
|
||||
|
||||
import Logger = require('./logger');
|
||||
import { getQemuPath, installQemu } from './qemu';
|
||||
|
||||
export { QEMU_BIN_NAME } from './qemu';
|
||||
export * from './qemu';
|
||||
|
||||
export async function installQemuIfNeeded(
|
||||
emulated: boolean,
|
||||
logger: Logger,
|
||||
arch: string,
|
||||
docker: Dockerode,
|
||||
): Promise<boolean> {
|
||||
// call platformNeedsQemu() regardless of whether emulation is required,
|
||||
// because it logs useful information
|
||||
const needsQemu = await platformNeedsQemu(docker, logger);
|
||||
if (!emulated || !needsQemu) {
|
||||
return false;
|
||||
}
|
||||
const fs = await import('mz/fs');
|
||||
if (!(await fs.exists(await getQemuPath(arch)))) {
|
||||
logger.logInfo(`Installing qemu for ${arch} emulation...`);
|
||||
await installQemu(arch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Docker daemon (including balenaEngine) requires explicit
|
||||
* QEMU emulation setup. Note that Docker Desktop (Windows and Mac), and also
|
||||
* the older Docker for Mac, have built-in support for binfmt_misc, so they
|
||||
* do not require explicit QEMU setup. References:
|
||||
* - https://en.wikipedia.org/wiki/Binfmt_misc
|
||||
* - https://docs.docker.com/docker-for-mac/multi-arch/
|
||||
* - https://www.ecliptik.com/Cross-Building-and-Running-Multi-Arch-Docker-Images/
|
||||
* - https://stackoverflow.com/questions/55388725/run-linux-arm-container-via-qemu-binfmt-misc-on-docker-lcow
|
||||
*
|
||||
* @param docker Dockerode instance
|
||||
*/
|
||||
async function platformNeedsQemu(
|
||||
docker: Dockerode,
|
||||
logger: Logger,
|
||||
): Promise<boolean> {
|
||||
const dockerInfo = await docker.info();
|
||||
// Docker Desktop (Windows and Mac) with Docker Engine 19.03 reports:
|
||||
// OperatingSystem: Docker Desktop
|
||||
// OSType: linux
|
||||
// Docker for Mac with Docker Engine 18.06 reports:
|
||||
// OperatingSystem: Docker for Mac
|
||||
// OSType: linux
|
||||
// On Ubuntu (standard Docker installation):
|
||||
// OperatingSystem: Ubuntu 18.04.2 LTS (containerized)
|
||||
// OSType: linux
|
||||
// https://stackoverflow.com/questions/38223965/how-can-i-detect-if-docker-for-mac-is-installed
|
||||
const isDockerDesktop = /(?:Docker Desktop)|(?:Docker for Mac)/i.test(
|
||||
dockerInfo.OperatingSystem,
|
||||
);
|
||||
if (isDockerDesktop) {
|
||||
logger.logInfo(stripIndent`
|
||||
Docker Desktop detected (daemon architecture: "${dockerInfo.Architecture}")
|
||||
Docker itself will determine and enable architecture emulation if required,
|
||||
without balena-cli intervention and regardless of the --emulated option.`);
|
||||
}
|
||||
return !isDockerDesktop;
|
||||
}
|
@ -15,8 +15,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import * as Promise from 'bluebird';
|
||||
import * as Bluebird from 'bluebird';
|
||||
import { stripIndent } from 'common-tags';
|
||||
import Dockerode = require('dockerode');
|
||||
import { getBalenaSdk } from './lazy';
|
||||
import Logger = require('./logger');
|
||||
|
||||
export const QEMU_VERSION = 'v4.0.0+balena2';
|
||||
export const QEMU_BIN_NAME = 'qemu-execve';
|
||||
|
||||
@ -34,14 +38,14 @@ export function copyQemu(context: string, arch: string) {
|
||||
const binDir = path.join(context, '.balena');
|
||||
const binPath = path.join(binDir, QEMU_BIN_NAME);
|
||||
|
||||
return Promise.resolve(fs.mkdir(binDir))
|
||||
return Bluebird.resolve(fs.mkdir(binDir))
|
||||
.catch({ code: 'EEXIST' }, function() {
|
||||
// noop
|
||||
})
|
||||
.then(() => getQemuPath(arch))
|
||||
.then(
|
||||
qemu =>
|
||||
new Promise(function(resolve, reject) {
|
||||
new Bluebird(function(resolve, reject) {
|
||||
const read = fs.createReadStream(qemu);
|
||||
const write = fs.createWriteStream(binPath);
|
||||
|
||||
@ -62,7 +66,7 @@ export const getQemuPath = function(arch: string) {
|
||||
const fs = require('mz/fs') as typeof import('mz/fs');
|
||||
|
||||
return balena.settings.get('binDirectory').then(binDir =>
|
||||
Promise.resolve(fs.mkdir(binDir))
|
||||
Bluebird.resolve(fs.mkdir(binDir))
|
||||
.catch({ code: 'EEXIST' }, function() {
|
||||
// noop
|
||||
})
|
||||
@ -80,7 +84,7 @@ export function installQemu(arch: string) {
|
||||
|
||||
return getQemuPath(arch).then(
|
||||
qemuPath =>
|
||||
new Promise(function(resolve, reject) {
|
||||
new Bluebird(function(resolve, reject) {
|
||||
const installStream = fs.createWriteStream(qemuPath);
|
||||
|
||||
const qemuArch = balenaArchToQemuArch(arch);
|
||||
@ -127,3 +131,62 @@ const balenaArchToQemuArch = function(arch: string) {
|
||||
throw new Error(`Cannot install emulator for architecture ${arch}`);
|
||||
}
|
||||
};
|
||||
|
||||
export async function installQemuIfNeeded(
|
||||
emulated: boolean,
|
||||
logger: Logger,
|
||||
arch: string,
|
||||
docker: Dockerode,
|
||||
): Promise<boolean> {
|
||||
// call platformNeedsQemu() regardless of whether emulation is required,
|
||||
// because it logs useful information
|
||||
const needsQemu = await platformNeedsQemu(docker, logger);
|
||||
if (!emulated || !needsQemu) {
|
||||
return false;
|
||||
}
|
||||
const fs = await import('mz/fs');
|
||||
if (!(await fs.exists(await getQemuPath(arch)))) {
|
||||
logger.logInfo(`Installing qemu for ${arch} emulation...`);
|
||||
await installQemu(arch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the Docker daemon (including balenaEngine) requires explicit
|
||||
* QEMU emulation setup. Note that Docker Desktop (Windows and Mac), and also
|
||||
* the older Docker for Mac, have built-in support for binfmt_misc, so they
|
||||
* do not require explicit QEMU setup. References:
|
||||
* - https://en.wikipedia.org/wiki/Binfmt_misc
|
||||
* - https://docs.docker.com/docker-for-mac/multi-arch/
|
||||
* - https://www.ecliptik.com/Cross-Building-and-Running-Multi-Arch-Docker-Images/
|
||||
* - https://stackoverflow.com/questions/55388725/run-linux-arm-container-via-qemu-binfmt-misc-on-docker-lcow
|
||||
*
|
||||
* @param docker Dockerode instance
|
||||
*/
|
||||
async function platformNeedsQemu(
|
||||
docker: Dockerode,
|
||||
logger: Logger,
|
||||
): Promise<boolean> {
|
||||
const dockerInfo = await docker.info();
|
||||
// Docker Desktop (Windows and Mac) with Docker Engine 19.03 reports:
|
||||
// OperatingSystem: Docker Desktop
|
||||
// OSType: linux
|
||||
// Docker for Mac with Docker Engine 18.06 reports:
|
||||
// OperatingSystem: Docker for Mac
|
||||
// OSType: linux
|
||||
// On Ubuntu (standard Docker installation):
|
||||
// OperatingSystem: Ubuntu 18.04.2 LTS (containerized)
|
||||
// OSType: linux
|
||||
// https://stackoverflow.com/questions/38223965/how-can-i-detect-if-docker-for-mac-is-installed
|
||||
const isDockerDesktop = /(?:Docker Desktop)|(?:Docker for Mac)/i.test(
|
||||
dockerInfo.OperatingSystem,
|
||||
);
|
||||
if (isDockerDesktop) {
|
||||
logger.logInfo(stripIndent`
|
||||
Docker Desktop detected (daemon architecture: "${dockerInfo.Architecture}")
|
||||
Docker itself will determine and enable architecture emulation if required,
|
||||
without balena-cli intervention and regardless of the --emulated option.`);
|
||||
}
|
||||
return !isDockerDesktop;
|
||||
}
|
||||
|
@ -176,7 +176,6 @@ describe('balena build', function() {
|
||||
copyQemu: async () => '',
|
||||
});
|
||||
mock.reRequire('../../build/utils/qemu');
|
||||
mock.reRequire('../../build/utils/qemu-ts');
|
||||
docker.expectGetInfo({ OperatingSystem: 'balenaOS 2.44.0+rev1' });
|
||||
await testDockerBuildStream({
|
||||
commandLine: `build ${projectPath} --emulated --deviceType ${deviceType} --arch ${arch}`,
|
||||
|
@ -20,7 +20,7 @@ import { expect } from 'chai';
|
||||
describe('resin-multibuild consistency', function() {
|
||||
it('should use the same values for selected constants', async () => {
|
||||
const { QEMU_BIN_NAME: MQEMU_BIN_NAME } = await import('resin-multibuild');
|
||||
const { QEMU_BIN_NAME } = await import('../../build/utils/qemu-ts');
|
||||
const { QEMU_BIN_NAME } = await import('../../build/utils/qemu');
|
||||
expect(QEMU_BIN_NAME).to.equal(MQEMU_BIN_NAME);
|
||||
});
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user