From a24a4dcc9789fc41f626bdd6868bda2a22cda123 Mon Sep 17 00:00:00 2001 From: wrench-exile-legacy Date: Sun, 14 Jun 2026 15:42:33 +0100 Subject: [PATCH] mailspring: build from source, 1.21.1 -> 1.22.0 --- pkgs/by-name/ma/mailspring/darwin.nix | 34 ------ pkgs/by-name/ma/mailspring/libetpan.nix | 49 ++++++++ pkgs/by-name/ma/mailspring/linux.nix | 101 ---------------- pkgs/by-name/ma/mailspring/mailcore2.nix | 106 +++++++++++++++++ pkgs/by-name/ma/mailspring/mailsync.nix | 138 +++++++++++++++++++++ pkgs/by-name/ma/mailspring/package.nix | 145 +++++++++++++++++++++-- 6 files changed, 428 insertions(+), 145 deletions(-) delete mode 100644 pkgs/by-name/ma/mailspring/darwin.nix create mode 100644 pkgs/by-name/ma/mailspring/libetpan.nix delete mode 100644 pkgs/by-name/ma/mailspring/linux.nix create mode 100644 pkgs/by-name/ma/mailspring/mailcore2.nix create mode 100644 pkgs/by-name/ma/mailspring/mailsync.nix diff --git a/pkgs/by-name/ma/mailspring/darwin.nix b/pkgs/by-name/ma/mailspring/darwin.nix deleted file mode 100644 index 77750ef76453..000000000000 --- a/pkgs/by-name/ma/mailspring/darwin.nix +++ /dev/null @@ -1,34 +0,0 @@ -{ - stdenv, - fetchurl, - pname, - version, - meta, - unzip, - makeWrapper, -}: - -stdenv.mkDerivation (finalAttrs: { - inherit pname version meta; - - src = fetchurl { - url = "https://github.com/Foundry376/Mailspring/releases/download/${finalAttrs.version}/Mailspring-AppleSilicon.zip"; - hash = "sha256-U8yh7Qsxu1AmqMVV2p9MmvNHH922yBEqWA8OsQleoCQ="; - }; - dontUnpack = true; - - nativeBuildInputs = [ - unzip - makeWrapper - ]; - - installPhase = '' - runHook preInstall - - mkdir -p $out/Applications $out/bin - unzip $src -d $out/Applications - makeWrapper $out/Applications/Mailspring.app/Contents/MacOS/Mailspring $out/bin/mailspring - - runHook postInstall - ''; -}) diff --git a/pkgs/by-name/ma/mailspring/libetpan.nix b/pkgs/by-name/ma/mailspring/libetpan.nix new file mode 100644 index 000000000000..93341ca2145b --- /dev/null +++ b/pkgs/by-name/ma/mailspring/libetpan.nix @@ -0,0 +1,49 @@ +{ + lib, + stdenv, + + src, + version, + + autoreconfHook, + pkg-config, + + cyrus_sasl, + openssl, + zlib, +}: +stdenv.mkDerivation { + pname = "mailspring-libetpan"; + inherit src version; + + sourceRoot = "${src.name}/mailsync/Vendor/libetpan"; + + nativeBuildInputs = [ + autoreconfHook + pkg-config + ]; + + buildInputs = [ + cyrus_sasl + openssl + zlib + ]; + + configureFlags = [ + "--with-sasl=${cyrus_sasl.dev}" + "--with-openssl=${openssl.dev}" + ]; + + # Prevent GCC 14 from treating pointer type mismatches as fatal build errors + env.CFLAGS = toString [ + "-std=gnu17" + "-Wno-error=incompatible-pointer-types" + ]; + + meta = { + description = "Modified fork of the libetpan mail framework"; + homepage = "https://github.com/Foundry376/Mailspring-Sync"; + license = lib.licenses.gpl3Plus; + platforms = lib.platforms.linux ++ lib.platforms.darwin; + }; +} diff --git a/pkgs/by-name/ma/mailspring/linux.nix b/pkgs/by-name/ma/mailspring/linux.nix deleted file mode 100644 index 54e04eb2e601..000000000000 --- a/pkgs/by-name/ma/mailspring/linux.nix +++ /dev/null @@ -1,101 +0,0 @@ -{ - stdenv, - lib, - pname, - version, - meta, - fetchurl, - autoPatchelfHook, - alsa-lib, - coreutils, - curl, - db, - dpkg, - glib, - gtk3, - wrapGAppsHook3, - libkrb5, - libsecret, - nss, - openssl, - udev, - libxtst, - libxscrnsaver, - libxdamage, - libxshmfence, - libxkbfile, - libgbm, - libdrm, - libappindicator, -}: - -stdenv.mkDerivation (finalAttrs: { - inherit pname version meta; - - src = fetchurl { - url = "https://github.com/Foundry376/Mailspring/releases/download/${finalAttrs.version}/mailspring-${finalAttrs.version}-amd64.deb"; - hash = "sha256-pyEWypqujSYYmbpUgcUMJoew4nIjE/dQWTVdYTxhmN4="; - }; - - nativeBuildInputs = [ - autoPatchelfHook - dpkg - wrapGAppsHook3 - ]; - - buildInputs = [ - alsa-lib - db - glib - gtk3 - libkrb5 - libsecret - nss - libxkbfile - libxdamage - libxscrnsaver - libxtst - libxshmfence - libgbm - libdrm - openssl - curl - ]; - - runtimeDependencies = [ - coreutils - openssl - (lib.getLib udev) - libappindicator - libsecret - ]; - - unpackPhase = '' - runHook preUnpack - - dpkg -x $src . - - runHook postUnpack - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out/{bin,lib} - cp -ar ./usr/share $out - - substituteInPlace $out/share/mailspring/resources/app.asar.unpacked/mailsync \ - --replace-fail dirname ${coreutils}/bin/dirname - - ln -s $out/share/mailspring/mailspring $out/bin/mailspring - ln -s ${lib.getLib openssl}/lib/libcrypto.so $out/lib/libcrypto.so.1.0.0 - - runHook postInstall - ''; - - postFixup = # sh - '' - substituteInPlace $out/share/applications/Mailspring.desktop \ - --replace-fail Exec=mailspring Exec=$out/bin/mailspring - ''; -}) diff --git a/pkgs/by-name/ma/mailspring/mailcore2.nix b/pkgs/by-name/ma/mailspring/mailcore2.nix new file mode 100644 index 000000000000..aa5c4e4f5ba9 --- /dev/null +++ b/pkgs/by-name/ma/mailspring/mailcore2.nix @@ -0,0 +1,106 @@ +{ + lib, + stdenv, + + src, + version, + + cmake, + pkg-config, + + glib, + icu, + mailspring-libetpan, + pcre2, + openssl, + cyrus_sasl, + html-tidy, + libuuid, + libctemplate, + libsysprof-capture, + libxml2, + zlib, +}: +stdenv.mkDerivation { + pname = "mailspring-mailcore2"; + inherit src version; + + sourceRoot = "${src.name}/mailsync/Vendor/mailcore2"; + + nativeBuildInputs = [ + cmake + pkg-config + ]; + + buildInputs = [ + cyrus_sasl + glib + html-tidy + icu + libctemplate + libsysprof-capture + libuuid + libxml2 + mailspring-libetpan + openssl + pcre2 + zlib + ]; + + # Prevent GCC 14 pointer errors + env = { + CXXFLAGS = toString [ + "-std=gnu++17" + "-Wno-error=incompatible-pointer-types" + ]; + + CFLAGS = toString [ + "-Wno-error=incompatible-pointer-types" + ]; + }; + + # Only build the core library, mimicking ./build.sh + buildFlags = [ "MailCore" ]; + + postPatch = '' + # Fix hardcoded impure paths + substituteInPlace CMakeLists.txt \ + --replace-fail "/usr/include/libxml2" "${lib.getDev libxml2}/include/libxml2" \ + --replace-fail "/usr/include/tidy" "${lib.getDev html-tidy}/include/tidy" + + '' + + lib.optionalString stdenv.hostPlatform.isDarwin '' + # Tell CMake to build with Objective C if the file is C, otherwise Objective C++ if the file is C++. + substituteInPlace CMakeLists.txt \ + --replace-fail "project (mailcore2)" "project (mailcore2 C CXX OBJC OBJCXX) + add_compile_options(\"$<$:-xobjective-c>\" \"$<$:-xobjective-c++>\")" + + # Fix old tidy header reference + substituteInPlace src/core/basetypes/MCHTMLCleaner.cpp \ + --replace-fail "buffio.h" "tidybuffio.h" + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/lib $out/include + + cp src/libMailCore.* $out/lib/ + + cp -r src/include/MailCore $out/include/ + + runHook postInstall + ''; + + meta = { + description = "Modified fork of the mailcore2 asynchronous C++ framework"; + homepage = "https://github.com/Foundry376/Mailspring-Sync"; + license = lib.licenses.gpl3Plus; + platforms = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + }; +} diff --git a/pkgs/by-name/ma/mailspring/mailsync.nix b/pkgs/by-name/ma/mailspring/mailsync.nix new file mode 100644 index 000000000000..cd112e3b4740 --- /dev/null +++ b/pkgs/by-name/ma/mailspring/mailsync.nix @@ -0,0 +1,138 @@ +{ + lib, + stdenv, + callPackage, + + src, + version, + + autoPatchelfHook, + cmake, + pkg-config, + + c-ares, + curl, + cyrus_sasl, + glib, + html-tidy, + icu, + libctemplate, + libiconv, + libsysprof-capture, + libuuid, + libxml2, + pcre2, + sqlite, + xz, + zlib, +}: +let + # libetpan and mailcore2 have both been modified from their upstream sources, so we must provide the vendored derivations + # See: https://github.com/Foundry376/Mailspring/blob/master/mailsync/Vendor/README.md + mailspring-libetpan = callPackage ./libetpan.nix { inherit src version; }; + mailspring-mailcore2 = callPackage ./mailcore2.nix { inherit src version mailspring-libetpan; }; +in +stdenv.mkDerivation { + pname = "mailspring-sync"; + inherit src version; + + sourceRoot = "${src.name}/mailsync"; + + nativeBuildInputs = [ + cmake + pkg-config + ] + ++ lib.optionals stdenv.isLinux [ + autoPatchelfHook + ]; + + buildInputs = [ + c-ares + curl + cyrus_sasl + glib + html-tidy + icu + libctemplate + libsysprof-capture + libuuid + libxml2 + mailspring-libetpan + mailspring-mailcore2 + pcre2 + sqlite + xz + zlib + ] + ++ lib.optionals stdenv.isDarwin [ + libiconv + ]; + + runtimeDependencies = [ + html-tidy + ]; + + env = + let + FLAGS = toString [ + "-Wno-error=deprecated-declarations" + "-Wno-error=incompatible-pointer-types" + ]; + in + { + CFLAGS = FLAGS; + CXXFLAGS = FLAGS; + }; + + postPatch = '' + substituteInPlace CMakeLists.txt \ + --replace-fail 'IF(''${CMAKE_SYSTEM_NAME} MATCHES "Linux")' 'if(TRUE)' + + # Replace hardcoded host paths and vendored dependencies + substituteInPlace CMakeLists.txt \ + --replace-fail "/usr/include/libxml2" "${lib.getDev libxml2}/include/libxml2" \ + --replace-fail "find_library(RESOLV_LIB NAMES libresolv.a libresolv)" "set(RESOLV_LIB \"resolv\")" \ + --replace-fail "target_link_libraries(mailsync libetpan.a)" "target_link_libraries(mailsync ${mailspring-libetpan}/lib/libetpan${stdenv.hostPlatform.extensions.sharedLibrary})" \ + --replace-fail "target_link_libraries(mailsync libMailCore.a)" "target_link_libraries(mailsync ${mailspring-mailcore2}/lib/libMailCore.a)" + + # Replace hardcoded references to archives with library references + # Transforms 'NAMES libfoo.a libfoo' into 'NAMES foo' + sed -i -E 's/NAMES lib([a-zA-Z0-9]+)\.a lib\1/NAMES \1/g' CMakeLists.txt + '' + + lib.optionalString stdenv.isDarwin '' + # UUID_LIB is provided by system frameworks + substituteInPlace CMakeLists.txt \ + --replace-fail "find_library(UUID_LIB NAMES uuid)" "set(UUID_LIB \"\")" + + # Remove GCC related linker flags + substituteInPlace CMakeLists.txt \ + --replace-fail 'set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++")' "" + + # Inject system frameworks and dependencies + substituteInPlace CMakeLists.txt \ + --replace-fail 'target_link_libraries(mailsync pthread sasl2 ssl crypto curl dl)' \ + 'target_link_libraries(mailsync pthread sasl2 ssl crypto curl dl tidy iconv "-framework Foundation" "-framework CoreFoundation" "-framework Security" "-framework CoreServices" "-framework SystemConfiguration")' + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/bin + + cp mailsync $out/bin + + runHook postInstall + ''; + + meta = { + description = "Email synchronization engine for Mailspring"; + homepage = "https://github.com/Foundry376/Mailspring-Sync"; + license = lib.licenses.gpl3Plus; + platforms = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + }; +} diff --git a/pkgs/by-name/ma/mailspring/package.nix b/pkgs/by-name/ma/mailspring/package.nix index 37011710992f..d1e320d9d25b 100644 --- a/pkgs/by-name/ma/mailspring/package.nix +++ b/pkgs/by-name/ma/mailspring/package.nix @@ -1,31 +1,156 @@ { lib, - stdenv, + buildNpmPackage, callPackage, + fetchFromGitHub, + + makeBinaryWrapper, + pkg-config, + wrapGAppsHook3, + zip, + + electron_41, + html-tidy, + + # Command line arguments which are always set e.g "--password-store=kwallet6" + commandLineArgs ? "", }: let + version = "1.22.0"; + + src = fetchFromGitHub { + owner = "Foundry376"; + repo = "Mailspring"; + tag = version; + hash = "sha256-32d0WIWqCsZlvuT+RDa3EYxkwTxWzQyLIfASiDfZnL8="; + fetchSubmodules = true; + }; + + electron = electron_41; + + mailspring-sync = callPackage ./mailsync.nix { inherit src version; }; + + mailspring-app = buildNpmPackage { + pname = "mailspring-app"; + inherit version src; + sourceRoot = "${src.name}/app"; + npmDepsHash = "sha256-b8CscOVVIbjkdf977LVVzFkWxOwn8XOemYpud5yK6vU="; + dontNpmBuild = true; + env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; + + npmFlags = [ "--ignore-scripts" ]; + + makeCacheWritable = true; + installPhase = '' + cp -r . "$out" + ''; + + meta = { + description = "Node dependencies for the Mailspring electron frontend"; + license = lib.licenses.gpl3Plus; + platforms = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + }; + }; +in +buildNpmPackage (finalAttrs: { pname = "mailspring"; - version = "1.21.1"; + inherit version src; + + npmDepsHash = "sha256-3uidHfxgGONdtwAnoVytIbRqRjwtz3Yu8tNQ0qT8mJQ="; + + nativeBuildInputs = [ + makeBinaryWrapper + pkg-config + wrapGAppsHook3 + zip + ]; + + npmFlags = [ "--ignore-scripts" ]; + + env.ELECTRON_SKIP_BINARY_DOWNLOAD = "1"; + + # Remove the postinstall script to stop it from downloading a recompiled mailspring-sync binary + postPatch = '' + echo "" > scripts/postinstall.js + ''; + + preConfigure = '' + chmod +w app + cp -r ${mailspring-app}/node_modules app/node_modules + chmod -R u+w app/node_modules + + cp ${mailspring-sync}/bin/mailsync app/mailsync + + # Remove nix sandbox violating steps from the build script + substituteInPlace app/build/build.js \ + --replace-fail "runWriteCommitHashIntoPackage," "" \ + --replace-fail "runUpdateSandboxHelperPermissions," "" \ + --replace-fail "runCopySymlinkedPackages," "" \ + --replace-fail "process.argv.includes('--skip-installers')" "true" + + # Use npm env vars to make node-gyp compile against the electron ABI + export npm_config_target="${electron.version}" + export npm_config_nodedir="${electron.headers}" + + # Create the electron archive to be used by electron-packager + cp -r ${electron.dist} electron-dist + chmod -R u+w electron-dist + + pushd electron-dist + zip -0Xqr ../electron.zip . + popd + + rm -r electron-dist + + # force @electron/packager to use our electron instead of downloading it + substituteInPlace \ + node_modules/@electron/packager/dist/packager.js \ + --replace-fail "await this.getElectronZipPath(downloadOpts)" "'$(pwd)/electron.zip'" + + pushd app + npm rebuild + popd + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share/mailspring $out/bin + + ASAR_PATH=$(find app/dist -name "app.asar" -print -quit) + cp -R "$(dirname "$ASAR_PATH")" $out/share/mailspring/resources + + makeWrapper ${lib.getExe electron} "$out/bin/mailspring" \ + --add-flags "$out/share/mailspring/resources/app.asar" \ + --prefix LD_LIBRARY_PATH : "${lib.makeLibraryPath [ html-tidy ]}" \ + --set-default ELECTRON_FORCE_IS_PACKAGED 1 \ + --add-flags ${lib.escapeShellArg commandLineArgs} + + runHook postInstall + ''; meta = { description = "Beautiful, fast and maintained fork of Nylas Mail by one of the original authors"; - downloadPage = "https://github.com/Foundry376/Mailspring"; + downloadPage = "https://github.com/Foundry376/Mailspring/releases"; + changelog = "https://github.com/Foundry376/Mailspring/releases/tag/${finalAttrs.version}"; homepage = "https://getmailspring.com"; license = lib.licenses.gpl3Plus; longDescription = '' Mailspring is an open-source mail client forked from Nylas Mail and built with Electron. - Mailspring's sync engine runs locally, but its source is not open. + Mailspring's sync engine is open source and written in C++ and C. It runs locally on your computer. ''; mainProgram = "mailspring"; maintainers = with lib.maintainers; [ wrench-exile-legacy ]; platforms = [ "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" "aarch64-darwin" ]; - sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ]; }; - - linux = callPackage ./linux.nix { inherit pname version meta; }; - darwin = callPackage ./darwin.nix { inherit pname version meta; }; -in -if stdenv.hostPlatform.isDarwin then darwin else linux +})