Merge branch 'main' of github.com:facebook/flipper into universalBuild

This commit is contained in:
2023-11-29 09:19:25 +01:00
103 changed files with 2466 additions and 1154 deletions

View File

@@ -26,6 +26,7 @@ import {
serverDir,
staticDir,
rootDir,
sonarDir,
} from './paths';
import isFB from './isFB';
import yargs from 'yargs';
@@ -244,7 +245,6 @@ async function copyStaticResources(outDir: string, versionNumber: string) {
'icon.png',
'icon_grey.png',
'icons.json',
'index.web.dev.html',
'index.web.html',
'install_desktop.svg',
'loading.html',
@@ -651,8 +651,11 @@ async function installNodeBinary(outputPath: string, platform: BuildPlatform) {
console.log(`✅ Node successfully downloaded and unpacked.`);
}
console.log(`⚙️ Copying node binary from ${nodePath} to ${outputPath}`);
await fs.copyFile(nodePath, outputPath);
console.log(`⚙️ Moving node binary from ${nodePath} to ${outputPath}`);
if (await fs.exists(outputPath)) {
await fs.rm(outputPath);
}
await fs.move(nodePath, outputPath);
} else {
console.log(`⚙️ Downloading node version for ${platform} using pkg-fetch`);
const nodePath = await pkgFetch({
@@ -661,8 +664,11 @@ async function installNodeBinary(outputPath: string, platform: BuildPlatform) {
nodeRange: SUPPORTED_NODE_PLATFORM,
});
console.log(`⚙️ Copying node binary from ${nodePath} to ${outputPath}`);
await fs.copyFile(nodePath, outputPath);
console.log(`⚙️ Moving node binary from ${nodePath} to ${outputPath}`);
if (await fs.exists(outputPath)) {
await fs.rm(outputPath);
}
await fs.move(nodePath, outputPath);
}
if (
@@ -740,86 +746,138 @@ async function setUpWindowsBundle(outputDir: string) {
async function setUpMacBundle(
outputDir: string,
serverDir: string,
platform: BuildPlatform,
versionNumber: string,
): Promise<{nodePath: string; resourcesPath: string}> {
) {
console.log(`⚙️ Creating Mac bundle in ${outputDir}`);
let appTemplate = path.join(staticDir, 'flipper-server-app-template');
if (isFB) {
appTemplate = path.join(
staticDir,
'facebook',
'flipper-server-app-template',
platform,
);
console.info('⚙️ Using internal template from: ' + appTemplate);
}
let serverOutputDir = '';
let nodeBinaryFile = '';
await fs.copy(appTemplate, outputDir);
/**
* Use the most basic template for MacOS.
* - Copy the contents of the template into the output directory.
* - Replace the version placeholder value with the actual version.
*/
if (!isFB) {
const template = path.join(staticDir, 'flipper-server-app-template');
await fs.copy(template, outputDir);
function replacePropertyValue(
obj: any,
targetValue: string,
replacementValue: string,
): any {
if (typeof obj === 'object' && !Array.isArray(obj) && obj !== null) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = replacePropertyValue(
obj[key],
targetValue,
replacementValue,
);
function replacePropertyValue(
obj: any,
targetValue: string,
replacementValue: string,
): any {
if (typeof obj === 'object' && !Array.isArray(obj) && obj !== null) {
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = replacePropertyValue(
obj[key],
targetValue,
replacementValue,
);
}
}
} else if (typeof obj === 'string' && obj === targetValue) {
obj = replacementValue;
}
} else if (typeof obj === 'string' && obj === targetValue) {
obj = replacementValue;
return obj;
}
return obj;
console.log(`⚙️ Update plist with build information`);
const plistPath = path.join(
outputDir,
'Flipper.app',
'Contents',
'Info.plist',
);
/* eslint-disable node/no-sync*/
const pListContents: Record<any, any> = plist.readFileSync(plistPath);
replacePropertyValue(
pListContents,
'{flipper-server-version}',
versionNumber,
);
plist.writeBinaryFileSync(plistPath, pListContents);
/* eslint-enable node/no-sync*/
serverOutputDir = path.join(
outputDir,
'Flipper.app',
'Contents',
'Resources',
'server',
);
nodeBinaryFile = path.join(
outputDir,
'Flipper.app',
'Contents',
'MacOS',
'flipper-runtime',
);
} else {
serverOutputDir = path.join(
sonarDir,
'facebook',
'flipper-server',
'Resources',
'server',
);
nodeBinaryFile = path.join(
sonarDir,
'facebook',
'flipper-server',
'Resources',
'flipper-runtime',
);
}
console.log(`⚙️ Writing plist`);
const plistPath = path.join(
outputDir,
'Flipper.app',
'Contents',
'Info.plist',
);
/* eslint-disable node/no-sync*/
const pListContents: Record<any, any> = plist.readFileSync(plistPath);
replacePropertyValue(
pListContents,
'{flipper-server-version}',
versionNumber,
);
plist.writeBinaryFileSync(plistPath, pListContents);
/* eslint-enable node/no-sync*/
const resourcesOutputDir = path.join(
outputDir,
'Flipper.app',
'Contents',
'Resources',
'server',
);
if (!(await fs.exists(resourcesOutputDir))) {
await fs.mkdir(resourcesOutputDir);
if (await fs.exists(serverOutputDir)) {
await fs.rm(serverOutputDir, {recursive: true, force: true});
}
await fs.mkdirp(serverOutputDir);
console.log(`⚙️ Copying from ${serverDir} to ${serverOutputDir}`);
// Copy resources instead of moving. This is because we want to keep the original
// files in the right location because they are used whilst bundling for
// other platforms.
await fs.copy(serverDir, serverOutputDir, {
overwrite: true,
dereference: true,
});
console.log(`⚙️ Downloading compatible node version`);
await installNodeBinary(nodeBinaryFile, platform);
if (isFB) {
const {buildFlipperServer} = await import(
// @ts-ignore only used inside Meta
'./fb/build-flipper-server-macos'
);
const outputPath = await buildFlipperServer(versionNumber, false);
console.log(
`⚙️ Successfully built platform: ${platform}, output: ${outputPath}`,
);
const appPath = path.join(outputDir, 'Flipper.app');
await fs.emptyDir(appPath);
await fs.copy(outputPath, appPath);
// const appPath = path.join(outputDir, 'Flipper.app');
// if (await fs.exists(appPath)) {
// await fs.rm(appPath, {recursive: true, force: true});
// }
// await fs.move(outputPath, appPath);
}
const nodeOutputPath = path.join(
outputDir,
'Flipper.app',
'Contents',
'MacOS',
'flipper-runtime',
);
return {resourcesPath: resourcesOutputDir, nodePath: nodeOutputPath};
}
async function bundleServerReleaseForPlatform(
dir: string,
bundleDir: string,
versionNumber: string,
platform: BuildPlatform,
) {
@@ -830,39 +888,38 @@ async function bundleServerReleaseForPlatform(
);
await fs.mkdirp(outputDir);
let outputPaths = {
nodePath: path.join(outputDir, 'flipper-runtime'),
resourcesPath: outputDir,
};
// On the mac, we need to set up a resource bundle which expects paths
// to be in different places from Linux/Windows bundles.
if (
platform === BuildPlatform.MAC_X64 ||
platform === BuildPlatform.MAC_AARCH64
) {
outputPaths = await setUpMacBundle(outputDir, platform, versionNumber);
} else if (platform === BuildPlatform.LINUX) {
await setUpLinuxBundle(outputDir);
} else if (platform === BuildPlatform.WINDOWS) {
await setUpWindowsBundle(outputDir);
}
await setUpMacBundle(outputDir, bundleDir, platform, versionNumber);
if (argv.dmg) {
await createMacDMG(platform, outputDir, distDir);
}
} else {
const outputPaths = {
nodePath: path.join(outputDir, 'flipper-runtime'),
resourcesPath: outputDir,
};
console.log(`⚙️ Copying from ${dir} to ${outputPaths.resourcesPath}`);
await fs.copy(dir, outputPaths.resourcesPath, {
overwrite: true,
dereference: true,
});
if (platform === BuildPlatform.LINUX) {
await setUpLinuxBundle(outputDir);
} else if (platform === BuildPlatform.WINDOWS) {
await setUpWindowsBundle(outputDir);
}
console.log(`⚙️ Downloading compatible node version`);
await installNodeBinary(outputPaths.nodePath, platform);
console.log(
`⚙️ Copying from ${bundleDir} to ${outputPaths.resourcesPath}`,
);
await fs.copy(bundleDir, outputPaths.resourcesPath, {
overwrite: true,
dereference: true,
});
if (
argv.dmg &&
(platform === BuildPlatform.MAC_X64 ||
platform === BuildPlatform.MAC_AARCH64)
) {
await createMacDMG(platform, outputDir, distDir);
console.log(`⚙️ Downloading compatible node version`);
await installNodeBinary(outputPaths.nodePath, platform);
}
console.log(`✅ Wrote ${platform}-specific server version to ${outputDir}`);

View File

@@ -210,6 +210,13 @@ async function buildDist(buildFolder: string) {
const targetsRaw: Map<Platform, Map<Arch, string[]>>[] = [];
const postBuildCallbacks: (() => void)[] = [];
const productName = process.env.FLIPPER_REACT_NATIVE_ONLY
? 'Flipper-Electron'
: 'Flipper';
const appId = process.env.FLIPPER_REACT_NATIVE_ONLY
? 'com.facebook.sonar-electron'
: `com.facebook.sonar`;
if (argv.mac || argv['mac-dmg']) {
targetsRaw.push(Platform.MAC.createTarget(['dir'], Arch.universal));
// You can build mac apps on Linux but can't build dmgs, so we separate those.
@@ -231,10 +238,14 @@ async function buildDist(buildFolder: string) {
}
}
postBuildCallbacks.push(() =>
spawn('zip', ['-qyr9', '../Flipper-mac.zip', 'Flipper.app'], {
cwd: macPath,
encoding: 'utf-8',
}),
spawn(
'zip',
['-qyr9', `../${productName}-mac.zip`, `${productName}.app`],
{
cwd: macPath,
encoding: 'utf-8',
},
),
);
}
if (argv.linux || argv['linux-deb'] || argv['linux-snap']) {
@@ -273,8 +284,8 @@ async function buildDist(buildFolder: string) {
await build({
publish: 'never',
config: {
appId: `com.facebook.sonar`,
productName: 'Flipper',
appId,
productName,
directories: {
buildResources: buildFolder,
output: distDir,

View File

@@ -10,6 +10,7 @@
import path from 'path';
export const rootDir = path.resolve(__dirname, '..');
export const sonarDir = path.resolve(__dirname, '..', '..');
export const appDir = path.join(rootDir, 'app');
export const browserUiDir = path.join(rootDir, 'flipper-ui-browser');
export const staticDir = path.join(rootDir, 'static');

View File

@@ -49,6 +49,11 @@ const argv = yargs
choices: ['stable', 'insiders'],
default: 'stable',
},
open: {
describe: 'Open Flipper in the default browser after starting',
type: 'boolean',
default: true,
},
})
.version('DEV')
.help()
@@ -103,7 +108,9 @@ async function copyStaticResources() {
async function restartServer() {
try {
await compileServerMain();
await launchServer(true, ++startCount === 1); // only open on the first time
// Only open the UI the first time it runs. Subsequent runs, likely triggered after
// saving changes, should just reload the existing UI.
await launchServer(true, argv.open && ++startCount === 1);
} catch (e) {
console.error(
chalk.red(