import { exec as execCb } from "node:child_process"; import * as fs from "node:fs/promises"; import * as path from "node:path"; import { env } from "node:process"; import { promisify } from "node:util"; const exec = promisify(execCb); const signId = env.APPLE_SIGNING_IDENTITY || "-"; /** * @param {string} origin * @param {string} target * @param {boolean} [rename] */ async function link(origin, target, rename) { const parent = path.dirname(target); await fs.mkdir(parent, { recursive: true, mode: 0o751 }); await (rename ? fs.rename(origin, target) : fs.symlink(path.relative(parent, origin), target)); } /** * Symlink shared libs paths for Linux * @param {string} root * @param {string} nativeDeps * @returns {Promise} */ export async function symlinkSharedLibsLinux(root, nativeDeps) { // rpath=${ORIGIN}/../lib/spacedrive const targetLib = path.join(root, "target", "lib"); const targetShare = path.join(root, "target", "share", "spacedrive"); const targetRPath = path.join(targetLib, "spacedrive"); const targetModelShare = path.join(targetShare, "models"); await Promise.all([ ...[targetRPath, targetModelShare].map((path) => fs.unlink(path).catch(() => {}) ), ...[targetLib, targetShare].map((path) => fs.mkdir(path, { recursive: true }) ), ]); await link(path.join(nativeDeps, "lib"), targetRPath); await link(path.join(nativeDeps, "models"), targetModelShare); } /** * Symlink shared libs paths for macOS * @param {string} root * @param {string} nativeDeps */ export async function symlinkSharedLibsMacOS(root, nativeDeps) { // rpath=@executable_path/../Frameworks/Spacedrive.framework const targetFrameworks = path.join(root, "target", "Frameworks"); // Framework const framework = path.join(nativeDeps, "Spacedrive.framework"); // Link Spacedrive.framework to target folder so sd-server can work ootb await fs.rm(targetFrameworks, { recursive: true }).catch(() => {}); await fs.mkdir(targetFrameworks, { recursive: true }); await link(framework, path.join(targetFrameworks, "Spacedrive.framework")); // Sign dylibs (Required for them to work on macOS 13+) await fs .readdir(path.join(framework, "Libraries"), { recursive: true, withFileTypes: true, }) .then((files) => Promise.all( files .filter((entry) => entry.isFile() && entry.name.endsWith(".dylib")) .map((entry) => exec( `codesign -s "${signId}" -f "${path.join(entry.path, entry.name)}"` ) ) ) ); } /** * Copy Windows DLLs for tauri build * @param {string} nativeDeps * @returns {Promise>} */ export async function windowsDLLs(nativeDeps) { return Object.fromEntries( await fs .readdir(path.join(nativeDeps, "bin"), { withFileTypes: true }) .then((files) => files .filter((entry) => entry.isFile() && entry.name.endsWith(".dll")) .map((entry) => [path.join(entry.path, entry.name), "."]) ) ); } /** * Symlink shared libs paths for Linux * @param {string} nativeDeps * @returns {Promise>} */ export async function linuxLibs(nativeDeps) { return Object.fromEntries( await fs .readdir(path.join(nativeDeps, "lib"), { withFileTypes: true }) .then((files) => Promise.all( files .filter( (entry) => (entry.isFile() || entry.isSymbolicLink()) && (entry.name.endsWith(".so") || entry.name.includes(".so.")) ) .map((entry) => [path.join(entry.path, entry.name), "."]) ) ) ); }