Ctrl K
ComunidadGuías…

scripts/mac-thin.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
// Each macOS app is built for one CPU (electron-builder.yml `mac.target`),
// but several vendored Mach-O files arrive universal. The app can only ever
// run its own slice, so packaging keeps that slice and drops the other.
import { execFile } from "node:child_process";
import { chmod, copyFile, open, rename, rm, stat } from "node:fs/promises";
import path from "node:path";
import { promisify } from "node:util";

const run = promisify(execFile);
const LIPO = "/usr/bin/lipo";
// Fat headers are big-endian; thin 32/64-bit headers appear in both byte orders.
const MACH_O_MAGIC = new Set([0xcafebabe, 0xcafebabf, 0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe]);

/** Node/electron-builder arch name -> lipo arch name. */
export const LIPO_ARCH = { arm64: "arm64", x64: "x86_64" };

export async function isMachO(file) {
  const handle = await open(file, "r");
  try {
    const { bytesRead, buffer } = await handle.read(Buffer.alloc(4), 0, 4, 0);
    return bytesRead === 4 && MACH_O_MAGIC.has(buffer.readUInt32BE(0));
  } finally {
    await handle.close();
  }
}

export async function machOArchs(file) {
  const { stdout } = await run(LIPO, ["-archs", file]);
  return stdout.trim().split(/\s+/);
}

/** Write only `arch`'s slice of `source` to `destination` (may be the same
 *  path). The bytes go to a temp file that is renamed into place, so another
 *  hard link to the destination never changes. Fails, writing nothing, when
 *  the slice is missing. */
export async function writeThinMachO(source, destination, arch) {
  const archs = await machOArchs(source);
  if (!archs.includes(arch)) throw new Error(`${source} has no ${arch} slice: [${archs.join(" ")}]`);
  if (source === destination && archs.length === 1) return;
  const temporary = path.join(path.dirname(destination), `.${path.basename(destination)}.${process.pid}.thin`);
  try {
    if (archs.length === 1) await copyFile(source, temporary);
    else await run(LIPO, [source, "-thin", arch, "-output", temporary]);
    await chmod(temporary, (await stat(source)).mode & 0o7777);
    const written = await machOArchs(temporary);
    if (written.join(" ") !== arch) throw new Error(`${destination} would be [${written.join(" ")}], not ${arch}`);
    await rename(temporary, destination);
  } finally {
    await rm(temporary, { force: true });
  }
}