From 01dfb8a9636965fe154192b07934670dd42509f3 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Wed, 1 Jun 2022 13:05:54 -0700 Subject: [PATCH] feat: don't lipo binaries that are identical in the x64 and arm64 versions and match an allowlist (#47) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: Don’t lipo binaries that are already a universal file or the same arch #17 Some Mach-O files may have already been fat binaries and will throw an error if lipoed again. Co-authored-by: Mitch Cohen Co-authored-by: Nick McGuire * Add a x64ArchFiles config key to allow allow-listing of files that are only always x64Arch Co-authored-by: Andrew Beyer Co-authored-by: Mitch Cohen Co-authored-by: Nick McGuire --- src/index.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/index.ts b/src/index.ts index cef9b58..2895a5e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -2,6 +2,7 @@ import { spawn } from '@malept/cross-spawn-promise'; import * as asar from 'asar'; import * as crypto from 'crypto'; import * as fs from 'fs-extra'; +import * as minimatch from 'minimatch'; import * as os from 'os'; import * as path from 'path'; import * as plist from 'plist'; @@ -39,6 +40,10 @@ type MakeUniversalOpts = { * Minimatch pattern of paths that are allowed to be present in one of the ASAR files, but not in the other. */ singleArchFiles?: string; + /** + * Minimatch pattern of binaries that are expected to be the same x64 binary in both of the ASAR files. + */ + x64ArchFiles?: string; }; const dupedFiles = (files: AppFile[]) => @@ -130,6 +135,27 @@ export const makeUniversalApp = async (opts: MakeUniversalOpts): Promise = const first = await fs.realpath(path.resolve(tmpApp, machOFile.relativePath)); const second = await fs.realpath(path.resolve(opts.arm64AppPath, machOFile.relativePath)); + const x64Sha = await sha(path.resolve(opts.x64AppPath, machOFile.relativePath)); + const arm64Sha = await sha(path.resolve(opts.arm64AppPath, machOFile.relativePath)); + if (x64Sha === arm64Sha) { + if ( + opts.x64ArchFiles === undefined || + !minimatch(machOFile.relativePath, opts.x64ArchFiles, { matchBase: true }) + ) { + throw new Error( + `Detected file "${machOFile.relativePath}" that's the same in both x64 and arm64 builds and not covered by the ` + + `x64ArchFiles rule: "${opts.x64ArchFiles}"`, + ); + } + + d( + 'SHA for Mach-O file', + machOFile.relativePath, + `matches across builds ${x64Sha}===${arm64Sha}, skipping lipo`, + ); + continue; + } + d('joining two MachO files with lipo', { first, second,