affine: add affine building from source (#358160)

This commit is contained in:
Weijia Wang 2024-12-16 18:10:35 +01:00 committed by GitHub
commit 323cbfdf60
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 385 additions and 66 deletions

View file

@ -24515,6 +24515,12 @@
github = "peterablehmann"; github = "peterablehmann";
githubId = 36541313; githubId = 36541313;
}; };
xiaoxiangmoe = {
name = "ZHAO JinXiang";
email = "xiaoxiangmoe@gmail.com";
github = "xiaoxiangmoe";
githubId = 8111351;
};
xinyangli = { xinyangli = {
email = "lixinyang411@gmail.com"; email = "lixinyang411@gmail.com";
matrix = "@me:xinyang.life"; matrix = "@me:xinyang.life";

View file

@ -0,0 +1,144 @@
{
copyDesktopItems,
electron,
fetchFromGitHub,
fetchurl,
lib,
makeDesktopItem,
makeWrapper,
stdenvNoCC,
unzip,
buildType ? "stable",
commandLineArgs ? "",
}:
let
hostPlatform = stdenvNoCC.hostPlatform;
nodePlatform = hostPlatform.parsed.kernel.name; # nodejs's `process.platform`
nodeArch = # nodejs's `process.arch`
{
"x86_64" = "x64";
"aarch64" = "arm64";
}
.${hostPlatform.parsed.cpu.name}
or (throw "affine-bin(${buildType}): unsupported CPU family ${hostPlatform.parsed.cpu.name}");
in
stdenvNoCC.mkDerivation (
finalAttrs:
(
{
# https://github.com/toeverything/AFFiNE/releases/tag/v0.18.1
version = "0.18.1";
githubSourceCode = fetchFromGitHub {
owner = "toeverything";
repo = "AFFiNE";
rev = "8b066a4b398aace25a20508a8e3c1a381721971f";
hash = "sha256-TWwojG3lqQlQFX3BKoFjJ27a3T/SawXgNDO6fP6gW4k=";
};
productName = if buildType == "stable" then "AFFiNE" else "AFFiNE-" + buildType;
binName = lib.toLower finalAttrs.productName;
pname = "${finalAttrs.binName}-bin";
meta =
{
description = "Workspace with fully merged docs, whiteboards and databases";
longDescription = ''
AFFiNE is an open-source, all-in-one workspace and an operating
system for all the building blocks that assemble your knowledge
base and much more -- wiki, knowledge management, presentation
and digital assets
'';
homepage = "https://affine.pro/";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [
richar
redyf
xiaoxiangmoe
];
platforms = [
"aarch64-darwin"
"x86_64-darwin"
"x86_64-linux"
];
sourceProvenance = [ lib.sourceTypes.binaryBytecode ];
}
// lib.optionalAttrs hostPlatform.isLinux {
mainProgram = finalAttrs.binName;
};
src = (
let
inherit (finalAttrs) version;
affinePrebuiltBinariesHashes = {
darwin-arm64 = "I8lOO97MNLkha0utWPAP4EKv9HiPMWpLi2ibvXjzjhdl7abgSPmMKbv1dGHxMzgMzGbDzhzKqzhYtJI+0Asfzw==";
darwin-x64 = "LZdd7yHJx9Hx0Po8NQgeDp0BhIyXGr0QsbF6bWP5pS08c4fdtE9UzNPfJGfzz/snTkWfKMQZop0Ea4fYGosr1Q==";
linux-x64 = "+impaFLuvcfpj4QjHwjZ06+fUpsxxRlk4eWO6+E4xkBMrV43gwZGeSeAw2pMgXogRGb/Oy6XUoA7o8tTQt9J6A==";
};
platform = if hostPlatform.isLinux then "linux" else "macos";
in
fetchurl {
# example: https://github.com/toeverything/AFFiNE/releases/download/v0.18.1/affine-0.18.1-stable-darwin-arm64.zip
url = "https://github.com/toeverything/AFFiNE/releases/download/v${version}/affine-${version}-${buildType}-${platform}-${nodeArch}.zip";
sha512 = affinePrebuiltBinariesHashes."${nodePlatform}-${nodeArch}";
}
);
nativeBuildInputs =
[
unzip
]
++ lib.optionals hostPlatform.isLinux [
copyDesktopItems
makeWrapper
];
installPhase =
let
inherit (finalAttrs) binName productName;
in
if hostPlatform.isDarwin then
''
runHook preInstall
mkdir -p $out/Applications
cd ..
mv ${productName}.app $out/Applications
runHook postInstall
''
else
''
runHook preInstall
mkdir --parents $out/lib/${binName}/
mv ./{resources,LICENSE*} $out/lib/${binName}/
install -Dm644 "${finalAttrs.githubSourceCode}/packages/frontend/apps/electron/resources/icons/icon_${buildType}_64x64.png" $out/share/icons/hicolor/64x64/apps/${binName}.png
makeWrapper "${electron}/bin/electron" $out/bin/${binName} \
--inherit-argv0 \
--add-flags $out/lib/${binName}/resources/app.asar \
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \
--add-flags ${lib.escapeShellArg commandLineArgs}
runHook postInstall
'';
}
// lib.optionalAttrs hostPlatform.isLinux {
desktopItems =
let
inherit (finalAttrs) binName productName;
in
[
(makeDesktopItem {
name = binName;
desktopName = productName;
comment = "AFFiNE Desktop App";
exec = "${binName} %U";
terminal = false;
icon = binName;
startupWMClass = binName;
categories = [ "Utility" ];
mimeTypes = [ "x-scheme-handler/${binName}" ];
})
];
}
)
)

View file

@ -1,75 +1,244 @@
{ {
lib, cacert,
fetchurl, cargo,
stdenvNoCC,
copyDesktopItems, copyDesktopItems,
electron_33,
fetchFromGitHub,
fetchurl,
findutils,
jq,
lib,
makeDesktopItem, makeDesktopItem,
makeWrapper, makeWrapper,
unzip, nodejs_20,
electron, rsync,
rustPlatform,
rustc,
stdenv,
stdenvNoCC,
yarn,
zip,
buildType ? "stable",
commandLineArgs ? "", commandLineArgs ? "",
}: }:
let
stdenvNoCC.mkDerivation ( hostPlatform = stdenvNoCC.hostPlatform;
nodePlatform = hostPlatform.parsed.kernel.name; # nodejs's `process.platform`
nodeArch = # nodejs's `process.arch`
{
"x86_64" = "x64";
"aarch64" = "arm64";
}
.${hostPlatform.parsed.cpu.name}
or (throw "affine(${buildType}): unsupported CPU family ${hostPlatform.parsed.cpu.name}");
electron = electron_33;
in
stdenv.mkDerivation (
finalAttrs: finalAttrs:
let (
icon = fetchurl { {
url = "https://raw.githubusercontent.com/toeverything/AFFiNE/v${finalAttrs.version}/packages/frontend/core/public/favicon-192.png"; productName = if buildType == "stable" then "AFFiNE" else "AFFiNE-" + buildType;
hash = "sha256-smZ5W7fy3TK3bvjwV4i71j2lVmKSZcyhMhcWfPxNnN4="; binName = lib.toLower finalAttrs.productName;
}; pname = finalAttrs.binName;
in
{ # https://github.com/toeverything/AFFiNE/releases/tag/v0.18.1
pname = "affine"; version = "0.18.1";
version = "0.17.5"; GITHUB_SHA = "8b066a4b398aace25a20508a8e3c1a381721971f";
src = fetchurl { src = fetchFromGitHub {
url = "https://github.com/toeverything/AFFiNE/releases/download/v${finalAttrs.version}/affine-${finalAttrs.version}-stable-linux-x64.zip"; owner = "toeverything";
hash = "sha256-lK5DDI9CKRneY4AwMI4r1qlGyYtQG4Xi8Ys4I3jawTk="; repo = "AFFiNE";
}; rev = finalAttrs.GITHUB_SHA;
nativeBuildInputs = [ hash = "sha256-TWwojG3lqQlQFX3BKoFjJ27a3T/SawXgNDO6fP6gW4k=";
copyDesktopItems };
makeWrapper
unzip meta =
]; {
postInstall = '' description = "Workspace with fully merged docs, whiteboards and databases";
mkdir -p $out/lib longDescription = ''
cp -r ./resources/* -t $out/lib/ AFFiNE is an open-source, all-in-one workspace and an operating
mkdir -p $out/share/doc/affine/ system for all the building blocks that assemble your knowledge
cp LICENSE* $out/share/doc/affine/ base and much more -- wiki, knowledge management, presentation
install -Dm644 ${icon} $out/share/pixmaps/affine.png and digital assets
makeWrapper "${electron}/bin/electron" $out/bin/affine \ '';
--inherit-argv0 \ homepage = "https://affine.pro/";
--add-flags $out/lib/app.asar \ license = lib.licenses.mit;
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \ maintainers = with lib.maintainers; [ xiaoxiangmoe ];
--add-flags ${lib.escapeShellArg commandLineArgs} platforms = [
''; "aarch64-darwin"
desktopItems = [ "aarch64-linux"
(makeDesktopItem { "x86_64-darwin"
name = "affine"; "x86_64-linux"
desktopName = "AFFiNE"; ];
exec = "affine %U"; sourceProvenance = [ lib.sourceTypes.fromSource ];
terminal = false; }
icon = "affine"; // lib.optionalAttrs hostPlatform.isLinux {
startupWMClass = "affine"; mainProgram = finalAttrs.binName;
categories = [ "Utility" ]; };
})
]; env = {
meta = { BUILD_TYPE = buildType;
description = "Workspace with fully merged docs, whiteboards and databases"; };
longDescription = '' cargoDeps = rustPlatform.fetchCargoVendor {
AFFiNE is an open-source, all-in-one workspace and an operating src = finalAttrs.src;
system for all the building blocks that assemble your knowledge hash = "sha256-5s/X9CD/H9rSn7SqMHioLg1KRP7y9fsozdFRY3hNiP8=";
base and much more -- wiki, knowledge management, presentation };
and digital assets yarnOfflineCache = stdenvNoCC.mkDerivation {
name = "yarn-offline-cache";
src = finalAttrs.src;
nativeBuildInputs = [
yarn
cacert
];
supportedArchitectures = builtins.toJSON {
os = [
"darwin"
"linux"
];
cpu = [
"arm64"
"x64"
];
libc = [
"glibc"
"musl"
];
};
buildPhase = ''
export HOME="$NIX_BUILD_TOP"
export CI=1
mkdir -p $out
yarn config set enableTelemetry false
yarn config set cacheFolder $out
yarn config set enableGlobalCache false
yarn config set supportedArchitectures --json "$supportedArchitectures"
yarn install --immutable --mode=skip-build
'';
dontInstall = true;
outputHashMode = "recursive";
outputHash = "sha256-HueTia+1ApfvbBK/b+iE84TB1DCWIDLoQ9XhjYlGCUs=";
};
nativeBuildInputs =
[
nodejs_20
yarn
cargo
rustc
findutils
zip
jq
rsync
]
++ lib.optionals hostPlatform.isLinux [
copyDesktopItems
makeWrapper
];
patchPhase = ''
runHook prePatchPhase
sed -i '/packagerConfig/a \ electronZipDir: process.env.ELECTRON_FORGE_ELECTRON_ZIP_DIR,' packages/frontend/apps/electron/forge.config.mjs
runHook postPatchPhase
''; '';
homepage = "https://affine.pro/";
downloadPage = "https://affine.pro/download"; configurePhase =
license = lib.licenses.mit; let
maintainers = with lib.maintainers; [ electronContentPath =
richar electron + (if hostPlatform.isLinux then "/libexec/electron/" else "/Applications/");
redyf in
]; ''
mainProgram = "affine"; runHook preConfigurePhase
platforms = [ "x86_64-linux" ];
}; export HOME="$NIX_BUILD_TOP"
} export CI=1
# cargo config
mkdir -p .cargo
cat $cargoDeps/.cargo/config.toml >> .cargo/config.toml
ln -s $cargoDeps @vendor@
# yarn config
yarn config set enableTelemetry false
yarn config set enableGlobalCache false
yarn config set cacheFolder $yarnOfflineCache
# electron config
ELECTRON_VERSION_IN_LOCKFILE=$(yarn why electron --json | tail --lines 1 | jq --raw-output '.children | to_entries | first | .key ' | cut -d : -f 2)
rsync --archive --chmod=u+w ${electronContentPath} $HOME/.electron-prebuilt-zip-tmp
export ELECTRON_FORGE_ELECTRON_ZIP_DIR=$PWD/.electron_zip_dir
mkdir -p $ELECTRON_FORGE_ELECTRON_ZIP_DIR
(cd $HOME/.electron-prebuilt-zip-tmp && zip --recurse-paths - .) > $ELECTRON_FORGE_ELECTRON_ZIP_DIR/electron-v$ELECTRON_VERSION_IN_LOCKFILE-${nodePlatform}-${nodeArch}.zip
export ELECTRON_SKIP_BINARY_DOWNLOAD=1
runHook postConfigurePhase
'';
buildPhase = ''
runHook preBuild
# first build
yarn workspaces focus @affine/electron @affine/monorepo
CARGO_NET_OFFLINE=true yarn workspace @affine/native build
BUILD_TYPE=${buildType} SKIP_NX_CACHE=1 yarn workspace @affine/electron generate-assets
# second build
yarn config set nmMode classic
yarn config set nmHoistingLimits workspaces
find . -name 'node_modules' -type d -prune -exec rm -rf '{}' +
yarn workspaces focus @affine/electron @affine/monorepo
BUILD_TYPE=${buildType} SKIP_WEB_BUILD=1 SKIP_BUNDLE=1 HOIST_NODE_MODULES=1 yarn workspace @affine/electron make
runHook postBuild
'';
installPhase =
let
inherit (finalAttrs) binName productName;
in
if hostPlatform.isDarwin then
''
runHook preInstall
mkdir -p $out/Applications
mv packages/frontend/apps/electron/out/${buildType}/${productName}-darwin-${nodeArch}/${productName}.app $out/Applications
runHook postInstall
''
else
''
runHook preInstall
mkdir --parents $out/lib/${binName}/
mv packages/frontend/apps/electron/out/${buildType}/${productName}-linux-${nodeArch}/{resources,LICENSE*} $out/lib/${binName}/
install -Dm644 packages/frontend/apps/electron/resources/icons/icon_${buildType}_64x64.png $out/share/icons/hicolor/64x64/apps/${binName}.png
makeWrapper "${electron}/bin/electron" $out/bin/${binName} \
--inherit-argv0 \
--add-flags $out/lib/${binName}/resources/app.asar \
--add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \
--add-flags ${lib.escapeShellArg commandLineArgs}
runHook postInstall
'';
}
// (lib.optionalAttrs hostPlatform.isLinux {
desktopItems =
let
inherit (finalAttrs) binName productName;
in
[
(makeDesktopItem {
name = binName;
desktopName = productName;
comment = "AFFiNE Desktop App";
exec = "${binName} %U";
terminal = false;
icon = binName;
startupWMClass = binName;
categories = [ "Utility" ];
mimeTypes = [ "x-scheme-handler/${binName}" ];
})
];
})
)
) )