diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 9dd0c568f2..a683a47725 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -63,7 +63,6 @@ jobs: - deltachat-rpc-server-armv7l-linux-wheel - deltachat-rpc-server-i686-linux - deltachat-rpc-server-i686-linux-wheel - - deltachat-rpc-server-source - deltachat-rpc-server-win32 - deltachat-rpc-server-win32-wheel - deltachat-rpc-server-win64 @@ -74,10 +73,9 @@ jobs: - libdeltachat - python-docs - # Fails to build - #- deltachat-repl-x86_64-android + - deltachat-repl-x86_64-android + - deltachat-rpc-server-x86_64-android #- deltachat-repl-x86-android - #- deltachat-rpc-server-x86_64-android #- deltachat-rpc-server-x86-android steps: - uses: actions/checkout@v6 @@ -85,6 +83,7 @@ jobs: show-progress: false persist-credentials: false - uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 + - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13 - run: nix build .#${{ matrix.installable }} build-macos: @@ -96,14 +95,12 @@ jobs: installable: - deltachat-rpc-server - deltachat-rpc-server-x86_64-darwin - - # Fails to build - # because of . - # - deltachat-rpc-server-aarch64-darwin + - deltachat-rpc-server-aarch64-darwin steps: - uses: actions/checkout@v6 with: show-progress: false persist-credentials: false - uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6 + - uses: DeterminateSystems/magic-nix-cache-action@565684385bcd71bad329742eefe8d12f2e765b39 # v13 - run: nix build .#${{ matrix.installable }} diff --git a/flake.nix b/flake.nix index 615a99c24a..d5094f39ea 100644 --- a/flake.nix +++ b/flake.nix @@ -29,11 +29,7 @@ rustc = fenixToolchain; }; manifest = (pkgs.lib.importTOML ./Cargo.toml).package; - androidSdk = android.sdk.${system} (sdkPkgs: - builtins.attrValues { - inherit (sdkPkgs) ndk-27-2-12479018 cmdline-tools-latest; - }); - androidNdkRoot = "${androidSdk}/share/android-sdk/ndk/27.2.12479018"; + version = manifest.version; rustSrc = nix-filter.lib { root = ./.; @@ -66,37 +62,15 @@ ]; }; - # Map from architecture name to rust targets and nixpkgs targets. + # Map from architecture name to nixpkgs targets. arch2targets = { - "x86_64-linux" = { - rustTarget = "x86_64-unknown-linux-musl"; - crossTarget = "x86_64-unknown-linux-musl"; - }; - "armv7l-linux" = { - rustTarget = "armv7-unknown-linux-musleabihf"; - crossTarget = "armv7l-unknown-linux-musleabihf"; - }; - "armv6l-linux" = { - rustTarget = "arm-unknown-linux-musleabihf"; - crossTarget = "armv6l-unknown-linux-musleabihf"; - }; - "aarch64-linux" = { - rustTarget = "aarch64-unknown-linux-musl"; - crossTarget = "aarch64-unknown-linux-musl"; - }; - "i686-linux" = { - rustTarget = "i686-unknown-linux-musl"; - crossTarget = "i686-unknown-linux-musl"; - }; - - "x86_64-darwin" = { - rustTarget = "x86_64-apple-darwin"; - crossTarget = "x86_64-darwin"; - }; - "aarch64-darwin" = { - rustTarget = "aarch64-apple-darwin"; - crossTarget = "aarch64-darwin"; - }; + "x86_64-linux" = "x86_64-unknown-linux-musl"; + "armv7l-linux" = "armv7l-unknown-linux-musleabihf"; + "armv6l-linux" = "armv6l-unknown-linux-musleabihf"; + "aarch64-linux" = "aarch64-unknown-linux-musl"; + "i686-linux" = "i686-unknown-linux-musl"; + "x86_64-darwin" = "x86_64-darwin"; + "aarch64-darwin" = "aarch64-darwin"; }; cargoLock = { lockFile = ./Cargo.lock; @@ -105,230 +79,29 @@ naersk'.buildPackage { pname = packageName; cargoBuildOptions = x: x ++ [ "--package" packageName ]; - version = manifest.version; - src = pkgs.lib.cleanSource ./.; - nativeBuildInputs = [ - pkgs.perl # Needed to build vendored OpenSSL. - ]; - auditable = false; # Avoid cargo-auditable failures. - doCheck = false; # Disable test as it requires network access. - }; - pkgsWin64 = pkgs.pkgsCross.mingwW64; - mkWin64RustPackage = packageName: - let - rustTarget = "x86_64-pc-windows-gnu"; - toolchainWin = fenixPkgs.combine [ - fenixPkgs.stable.rustc - fenixPkgs.stable.cargo - fenixPkgs.targets.${rustTarget}.stable.rust-std - ]; - naerskWin = pkgs.callPackage naersk { - cargo = toolchainWin; - rustc = toolchainWin; - }; - in - naerskWin.buildPackage rec { - pname = packageName; - cargoBuildOptions = x: x ++ [ "--package" packageName ]; - version = manifest.version; - strictDeps = true; + inherit version; src = pkgs.lib.cleanSource ./.; nativeBuildInputs = [ pkgs.perl # Needed to build vendored OpenSSL. ]; - depsBuildBuild = [ - pkgsWin64.stdenv.cc - ]; - buildInputs = [ - pkgsWin64.windows.pthreads - ]; auditable = false; # Avoid cargo-auditable failures. doCheck = false; # Disable test as it requires network access. - - CARGO_BUILD_TARGET = rustTarget; - TARGET_CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; - CARGO_BUILD_RUSTFLAGS = [ - "-C" - "linker=${TARGET_CC}" - "-L" - "native=${pkgsWin64.windows.pthreads}/lib" - ]; - - CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; - LD = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; - }; - - pkgsWin32 = pkgs.pkgsCross.mingw32; - mkWin32RustPackage = packageName: - let - rustTarget = "i686-pc-windows-gnu"; - in - let - toolchainWin = fenixPkgs.combine [ - fenixPkgs.stable.rustc - fenixPkgs.stable.cargo - fenixPkgs.targets.${rustTarget}.stable.rust-std - ]; - naerskWin = pkgs.callPackage naersk { - cargo = toolchainWin; - rustc = toolchainWin; - }; - - # Get rid of MCF Gthread library. - # See - # and - # for details. - # - # Use DWARF-2 instead of SJLJ for exception handling. - winCC = pkgsWin32.buildPackages.wrapCC ( - (pkgsWin32.buildPackages.gcc-unwrapped.override - ({ - threadsCross = { - model = "win32"; - package = null; - }; - })).overrideAttrs (oldAttr: { - configureFlags = oldAttr.configureFlags ++ [ - "--disable-sjlj-exceptions" - "--with-dwarf2" - ]; - }) - ); - in - naerskWin.buildPackage rec { - pname = packageName; - cargoBuildOptions = x: x ++ [ "--package" packageName ]; - version = manifest.version; - strictDeps = true; - src = pkgs.lib.cleanSource ./.; - nativeBuildInputs = [ - pkgs.perl # Needed to build vendored OpenSSL. - ]; - depsBuildBuild = [ - winCC - ]; - buildInputs = [ - pkgsWin32.windows.pthreads - ]; - auditable = false; # Avoid cargo-auditable failures. - doCheck = false; # Disable test as it requires network access. - - CARGO_BUILD_TARGET = rustTarget; - TARGET_CC = "${winCC}/bin/${winCC.targetPrefix}cc"; - CARGO_BUILD_RUSTFLAGS = [ - "-C" - "linker=${TARGET_CC}" - "-L" - "native=${pkgsWin32.windows.pthreads}/lib" - ]; - - CC = "${winCC}/bin/${winCC.targetPrefix}cc"; - LD = "${winCC}/bin/${winCC.targetPrefix}cc"; - }; - - mkCrossRustPackage = arch: packageName: - let - rustTarget = arch2targets."${arch}".rustTarget; - crossTarget = arch2targets."${arch}".crossTarget; - pkgsCross = import nixpkgs { - system = system; - crossSystem.config = crossTarget; - }; - in - let - toolchain = fenixPkgs.combine [ - fenixPkgs.stable.rustc - fenixPkgs.stable.cargo - fenixPkgs.targets.${rustTarget}.stable.rust-std - ]; - naersk-lib = pkgs.callPackage naersk { - cargo = toolchain; - rustc = toolchain; - }; - in - naersk-lib.buildPackage rec { - pname = packageName; - cargoBuildOptions = x: x ++ [ "--package" packageName ]; - version = manifest.version; - strictDeps = true; - src = rustSrc; - nativeBuildInputs = [ - pkgs.perl # Needed to build vendored OpenSSL. - ]; - auditable = false; # Avoid cargo-auditable failures. - doCheck = false; # Disable test as it requires network access. - - CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib"; - CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib"; - - CARGO_BUILD_TARGET = rustTarget; - TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; - CARGO_BUILD_RUSTFLAGS = [ - "-C" - "linker=${TARGET_CC}" - ]; - - CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; - LD = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; - }; - - androidAttrs = { - armeabi-v7a = { - cc = "armv7a-linux-androideabi21-clang"; - rustTarget = "armv7-linux-androideabi"; - }; - arm64-v8a = { - cc = "aarch64-linux-android21-clang"; - rustTarget = "aarch64-linux-android"; - }; - x86 = { - cc = "i686-linux-android21-clang"; - rustTarget = "i686-linux-android"; - }; - x86_64 = { - cc = "x86_64-linux-android21-clang"; - rustTarget = "x86_64-linux-android"; }; + mkWin64RustPackage = pkgs.callPackage ./nix/win64-package.nix { + inherit naersk system fenixPkgs version; }; - mkAndroidRustPackage = arch: packageName: - let - rustTarget = androidAttrs.${arch}.rustTarget; - toolchain = fenixPkgs.combine [ - fenixPkgs.stable.rustc - fenixPkgs.stable.cargo - fenixPkgs.targets.${rustTarget}.stable.rust-std - ]; - naersk-lib = pkgs.callPackage naersk { - cargo = toolchain; - rustc = toolchain; - }; - targetToolchain = "${androidNdkRoot}/toolchains/llvm/prebuilt/linux-x86_64"; - targetCcName = androidAttrs.${arch}.cc; - targetCc = "${targetToolchain}/bin/${targetCcName}"; - in - naersk-lib.buildPackage rec { - pname = packageName; - cargoBuildOptions = x: x ++ [ "--package" packageName ]; - version = manifest.version; - strictDeps = true; - src = rustSrc; - nativeBuildInputs = [ - pkgs.perl # Needed to build vendored OpenSSL. - ]; - auditable = false; # Avoid cargo-auditable failures. - doCheck = false; # Disable test as it requires network access. + mkWin32RustPackage = pkgs.callPackage ./nix/win32-package.nix { + inherit naersk system fenixPkgs version; + }; - CARGO_BUILD_TARGET = rustTarget; - TARGET_CC = "${targetCc}"; - CARGO_BUILD_RUSTFLAGS = [ - "-C" - "linker=${TARGET_CC}" - ]; + mkCrossRustPackage = pkgs.callPackage ./nix/cross-rust-package.nix { + inherit nixpkgs arch2targets naersk fenixPkgs system rustSrc version; + }; - CC = "${targetCc}"; - LD = "${targetCc}"; - }; + mkAndroidRustPackage = pkgs.callPackage ./nix/android-package.nix { + inherit naersk fenixPkgs system rustSrc android version; + }; mkAndroidPackages = arch: let @@ -338,32 +111,7 @@ "deltachat-rpc-server-${arch}-android" = rpc-server; "deltachat-repl-${arch}-android" = mkAndroidRustPackage arch "deltachat-repl"; "deltachat-rpc-server-${arch}-android-wheel" = - pkgs.stdenv.mkDerivation { - pname = "deltachat-rpc-server-${arch}-android-wheel"; - version = manifest.version; - src = nix-filter.lib { - root = ./.; - include = [ - "scripts/wheel-rpc-server.py" - "deltachat-rpc-server/README.md" - "LICENSE" - "Cargo.toml" - ]; - }; - nativeBuildInputs = [ - pkgs.python3 - pkgs.python3Packages.wheel - ]; - buildInputs = [ - rpc-server - ]; - buildPhase = '' - mkdir tmp - cp ${rpc-server}/bin/deltachat-rpc-server tmp/deltachat-rpc-server - python3 scripts/wheel-rpc-server.py ${arch}-android tmp/deltachat-rpc-server - ''; - installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out''; - }; + mkWheel { inherit rpc-server; arch = "${arch}-android"; }; }; mkRustPackages = arch: @@ -373,34 +121,10 @@ { "deltachat-repl-${arch}" = mkCrossRustPackage arch "deltachat-repl"; "deltachat-rpc-server-${arch}" = rpc-server; - "deltachat-rpc-server-${arch}-wheel" = - pkgs.stdenv.mkDerivation { - pname = "deltachat-rpc-server-${arch}-wheel"; - version = manifest.version; - src = nix-filter.lib { - root = ./.; - include = [ - "scripts/wheel-rpc-server.py" - "deltachat-rpc-server/README.md" - "LICENSE" - "Cargo.toml" - ]; - }; - nativeBuildInputs = [ - pkgs.python3 - pkgs.python3Packages.wheel - ]; - buildInputs = [ - rpc-server - ]; - buildPhase = '' - mkdir tmp - cp ${rpc-server}/bin/deltachat-rpc-server tmp/deltachat-rpc-server - python3 scripts/wheel-rpc-server.py ${arch} tmp/deltachat-rpc-server - ''; - installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out''; - }; + "deltachat-rpc-server-${arch}-wheel" = mkWheel { inherit rpc-server; arch = "${arch}"; }; }; + + mkWheel = pkgs.callPackage ./nix/wheel.nix { inherit nix-filter version; root = ./.; }; in { formatter = pkgs.nixpkgs-fmt; @@ -424,132 +148,29 @@ deltachat-repl-win64 = mkWin64RustPackage "deltachat-repl"; deltachat-rpc-server-win64 = mkWin64RustPackage "deltachat-rpc-server"; deltachat-rpc-server-win64-wheel = - pkgs.stdenv.mkDerivation { - pname = "deltachat-rpc-server-win64-wheel"; - version = manifest.version; - src = nix-filter.lib { - root = ./.; - include = [ - "scripts/wheel-rpc-server.py" - "deltachat-rpc-server/README.md" - "LICENSE" - "Cargo.toml" - ]; - }; - nativeBuildInputs = [ - pkgs.python3 - pkgs.python3Packages.wheel - ]; - buildInputs = [ - deltachat-rpc-server-win64 - ]; - buildPhase = '' - mkdir tmp - cp ${deltachat-rpc-server-win64}/bin/deltachat-rpc-server.exe tmp/deltachat-rpc-server.exe - python3 scripts/wheel-rpc-server.py win64 tmp/deltachat-rpc-server.exe - ''; - installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out''; - }; + mkWheel { rpc-server = deltachat-rpc-server-win64; arch = "win64"; binaryName = "deltachat-rpc-server.exe"; }; deltachat-repl-win32 = mkWin32RustPackage "deltachat-repl"; deltachat-rpc-server-win32 = mkWin32RustPackage "deltachat-rpc-server"; deltachat-rpc-server-win32-wheel = - pkgs.stdenv.mkDerivation { - pname = "deltachat-rpc-server-win32-wheel"; - version = manifest.version; - src = nix-filter.lib { - root = ./.; - include = [ - "scripts/wheel-rpc-server.py" - "deltachat-rpc-server/README.md" - "LICENSE" - "Cargo.toml" - ]; - }; - nativeBuildInputs = [ - pkgs.python3 - pkgs.python3Packages.wheel - ]; - buildInputs = [ - deltachat-rpc-server-win32 - ]; - buildPhase = '' - mkdir tmp - cp ${deltachat-rpc-server-win32}/bin/deltachat-rpc-server.exe tmp/deltachat-rpc-server.exe - python3 scripts/wheel-rpc-server.py win32 tmp/deltachat-rpc-server.exe - ''; - installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out''; - }; - # Run `nix build .#docs` to get C docs generated in `./result/`. - docs = - pkgs.stdenv.mkDerivation { - pname = "docs"; - version = manifest.version; - src = pkgs.lib.cleanSource ./.; - nativeBuildInputs = [ pkgs.doxygen ]; - buildPhase = ''scripts/run-doxygen.sh''; - installPhase = ''mkdir -p $out; cp -av deltachat-ffi/html deltachat-ffi/xml $out''; - }; - - libdeltachat = - let - rustPlatform = (pkgs.makeRustPlatform { - cargo = fenixToolchain; - rustc = fenixToolchain; - }); - in - pkgs.stdenv.mkDerivation { - pname = "libdeltachat"; - version = manifest.version; - src = rustSrc; - cargoDeps = pkgs.rustPlatform.importCargoLock cargoLock; - - nativeBuildInputs = [ - pkgs.perl # Needed to build vendored OpenSSL. - pkgs.cmake - rustPlatform.cargoSetupHook - fenixPkgs.stable.rustc - fenixPkgs.stable.cargo - ]; + mkWheel + { rpc-server = deltachat-rpc-server-win32; arch = "win32"; binaryName = "deltachat-rpc-server.exe"; }; - postInstall = '' - substituteInPlace $out/include/deltachat.h \ - --replace __FILE__ '"${placeholder "out"}/include/deltachat.h"' - ''; - }; + # Run `nix build .#docs` to get C docs generated in `./result/`. + docs = pkgs.callPackage ./nix/c-docs.nix { inherit version; }; - # Source package for deltachat-rpc-server. - # Fake package that downloads Linux version, - # needed to install deltachat-rpc-server on Android with `pip`. - deltachat-rpc-server-source = - pkgs.stdenv.mkDerivation { - pname = "deltachat-rpc-server-source"; - version = manifest.version; - src = pkgs.lib.cleanSource ./.; - nativeBuildInputs = [ - pkgs.python3 - pkgs.python3Packages.wheel - ]; - buildPhase = ''python3 scripts/wheel-rpc-server.py source deltachat_rpc_server-${manifest.version}.tar.gz''; - installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-${manifest.version}.tar.gz $out''; - }; + libdeltachat = pkgs.callPackage ./nix/libdeltachat.nix { + inherit fenixToolchain rustSrc cargoLock fenixPkgs version; + }; - deltachat-rpc-client = - pkgs.python3Packages.buildPythonPackage { - pname = "deltachat-rpc-client"; - version = manifest.version; - src = pkgs.lib.cleanSource ./deltachat-rpc-client; - format = "pyproject"; - propagatedBuildInputs = [ - pkgs.python3Packages.setuptools - pkgs.python3Packages.imap-tools - ]; - }; + deltachat-rpc-client = pkgs.callPackage ./nix/deltachat-rpc-client.nix { + inherit version; + }; deltachat-python = pkgs.python3Packages.buildPythonPackage { pname = "deltachat-python"; - version = manifest.version; + inherit version; src = pkgs.lib.cleanSource ./python; format = "pyproject"; buildInputs = [ @@ -567,51 +188,12 @@ pkgs.python3Packages.requests ]; }; - python-docs = - pkgs.stdenv.mkDerivation { - pname = "docs"; - version = manifest.version; - src = pkgs.lib.cleanSource ./.; - buildInputs = [ - deltachat-python - deltachat-rpc-client - pkgs.python3Packages.breathe - pkgs.python3Packages.sphinx-rtd-theme - ]; - nativeBuildInputs = [ pkgs.sphinx ]; - buildPhase = ''sphinx-build -b html -a python/doc/ dist/html''; - installPhase = ''mkdir -p $out; cp -av dist/html $out''; - }; - }; - - devShells.default = - let - pkgs = import nixpkgs { - system = system; - overlays = [ fenix.overlays.default ]; + python-docs = pkgs.callPackage ./nix/python-docs.nix { + inherit deltachat-python deltachat-rpc-client version; }; - in - pkgs.mkShell { - - buildInputs = with pkgs; [ - (fenix.packages.${system}.complete.withComponents [ - "cargo" - "clippy" - "rust-src" - "rustc" - "rustfmt" - ]) - cargo-deny - rust-analyzer-nightly - cargo-nextest - perl # needed to build vendored OpenSSL - git-cliff - (python3.withPackages (pypkgs: with pypkgs; [ - tox - ])) - nodejs - ]; }; + + devShells.default = import ./nix/devshell.nix { inherit nixpkgs fenix system; }; } ); } diff --git a/nix/android-package.nix b/nix/android-package.nix new file mode 100644 index 0000000000..1687046e42 --- /dev/null +++ b/nix/android-package.nix @@ -0,0 +1,63 @@ +{ pkgs, naersk, fenixPkgs, system, version, rustSrc, android }: +arch: packageName: +let + androidSdk = android.sdk.${system} (sdkPkgs: + builtins.attrValues { + inherit (sdkPkgs) ndk-27-2-12479018 cmdline-tools-latest; + }); + androidNdkRoot = "${androidSdk}/share/android-sdk/ndk/27.2.12479018"; + androidAttrs = { + armeabi-v7a = { + cc = "armv7a-linux-androideabi21-clang"; + rustTarget = "armv7-linux-androideabi"; + }; + arm64-v8a = { + cc = "aarch64-linux-android21-clang"; + rustTarget = "aarch64-linux-android"; + }; + x86 = { + cc = "i686-linux-android21-clang"; + rustTarget = "i686-linux-android"; + }; + x86_64 = { + cc = "x86_64-linux-android21-clang"; + rustTarget = "x86_64-linux-android"; + }; + }; + + rustTarget = androidAttrs.${arch}.rustTarget; + toolchain = fenixPkgs.combine [ + fenixPkgs.stable.rustc + fenixPkgs.stable.cargo + fenixPkgs.targets.${rustTarget}.stable.rust-std + ]; + naersk-lib = pkgs.callPackage naersk { + cargo = toolchain; + rustc = toolchain; + }; + targetToolchain = "${androidNdkRoot}/toolchains/llvm/prebuilt/linux-x86_64"; + targetCcName = androidAttrs.${arch}.cc; + targetCc = "${targetToolchain}/bin/${targetCcName}"; +in +naersk-lib.buildPackage rec { + pname = packageName; + cargoBuildOptions = x: x ++ [ "--package" packageName ]; + inherit version; + strictDeps = true; + src = rustSrc; + nativeBuildInputs = [ + pkgs.perl # Needed to build vendored OpenSSL. + ]; + auditable = false; # Avoid cargo-auditable failures. + doCheck = false; # Disable test as it requires network access. + + CARGO_BUILD_TARGET = rustTarget; + TARGET_CC = "${targetCc}"; + CARGO_BUILD_RUSTFLAGS = [ + "-C" + "linker=${TARGET_CC}" + ]; + + CC = "${targetCc}"; + LD = "${targetCc}"; +} diff --git a/nix/c-docs.nix b/nix/c-docs.nix new file mode 100644 index 0000000000..0b74f03d64 --- /dev/null +++ b/nix/c-docs.nix @@ -0,0 +1,9 @@ +{ pkgs, version }: +pkgs.stdenv.mkDerivation { + pname = "docs"; + inherit version; + src = pkgs.lib.cleanSource ../.; + nativeBuildInputs = [ pkgs.doxygen ]; + buildPhase = ''scripts/run-doxygen.sh''; + installPhase = ''mkdir -p $out; cp -av deltachat-ffi/html deltachat-ffi/xml $out''; +} diff --git a/nix/cross-rust-package.nix b/nix/cross-rust-package.nix new file mode 100644 index 0000000000..87f0c6e28d --- /dev/null +++ b/nix/cross-rust-package.nix @@ -0,0 +1,50 @@ +{ pkgs, nixpkgs, arch2targets, naersk, fenixPkgs, system, rustSrc, version }: +arch: packageName: +let + crossTarget = arch2targets."${arch}"; + pkgsCross = + if crossTarget == system then + import nixpkgs { inherit system; } + else + import nixpkgs { + system = system; + crossSystem.config = crossTarget; + }; + rustTarget = pkgsCross.stdenv.hostPlatform.rust.rustcTarget; + toolchain = fenixPkgs.combine [ + fenixPkgs.stable.rustc + fenixPkgs.stable.cargo + fenixPkgs.targets.${rustTarget}.stable.rust-std + ]; + naersk-lib = (pkgs.callPackage naersk { + cargo = toolchain; + rustc = toolchain; + }).override { + pkgs = pkgsCross; + }; +in +naersk-lib.buildPackage rec { + pname = packageName; + cargoBuildOptions = x: x ++ [ "--package" packageName ]; + inherit version; + strictDeps = true; + src = rustSrc; + nativeBuildInputs = [ + pkgsCross.buildPackages.perl # Needed to build vendored OpenSSL. + ]; + auditable = false; # Avoid cargo-auditable failures. + doCheck = false; # Disable test as it requires network access. + + CARGO_TARGET_X86_64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib"; + CARGO_TARGET_AARCH64_APPLE_DARWIN_RUSTFLAGS = "-Clink-args=-L${pkgsCross.libiconv}/lib"; + + CARGO_BUILD_TARGET = rustTarget; + TARGET_CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; + CARGO_BUILD_RUSTFLAGS = [ + "-C" + "linker=${TARGET_CC}" + ]; + + CC = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; + LD = "${pkgsCross.stdenv.cc}/bin/${pkgsCross.stdenv.cc.targetPrefix}cc"; +} diff --git a/nix/deltachat-rpc-client.nix b/nix/deltachat-rpc-client.nix new file mode 100644 index 0000000000..d266210f25 --- /dev/null +++ b/nix/deltachat-rpc-client.nix @@ -0,0 +1,11 @@ +{ pkgs, version }: +pkgs.python3Packages.buildPythonPackage { + pname = "deltachat-rpc-client"; + inherit version; + src = pkgs.lib.cleanSource ../deltachat-rpc-client; + format = "pyproject"; + propagatedBuildInputs = [ + pkgs.python3Packages.setuptools + pkgs.python3Packages.imap-tools + ]; +} diff --git a/nix/devshell.nix b/nix/devshell.nix new file mode 100644 index 0000000000..668873c806 --- /dev/null +++ b/nix/devshell.nix @@ -0,0 +1,27 @@ +{ nixpkgs, fenix, system }: +let + pkgs = import nixpkgs { + inherit system; + overlays = [ fenix.overlays.default ]; + }; +in +pkgs.mkShell { + buildInputs = with pkgs; [ + (fenix.packages.${system}.complete.withComponents [ + "cargo" + "clippy" + "rust-src" + "rustc" + "rustfmt" + ]) + cargo-deny + rust-analyzer-nightly + cargo-nextest + perl # needed to build vendored OpenSSL + git-cliff + (python3.withPackages (pypkgs: with pypkgs; [ + tox + ])) + nodejs + ]; +} diff --git a/nix/libdeltachat.nix b/nix/libdeltachat.nix new file mode 100644 index 0000000000..b45c73e03f --- /dev/null +++ b/nix/libdeltachat.nix @@ -0,0 +1,26 @@ +{ pkgs, fenixToolchain, rustSrc, cargoLock, fenixPkgs, version }: +let + rustPlatform = (pkgs.makeRustPlatform { + cargo = fenixToolchain; + rustc = fenixToolchain; + }); +in +pkgs.stdenv.mkDerivation { + pname = "libdeltachat"; + inherit version; + src = rustSrc; + cargoDeps = pkgs.rustPlatform.importCargoLock cargoLock; + + nativeBuildInputs = [ + pkgs.perl # Needed to build vendored OpenSSL. + pkgs.cmake + rustPlatform.cargoSetupHook + fenixPkgs.stable.rustc + fenixPkgs.stable.cargo + ]; + + postInstall = '' + substituteInPlace $out/include/deltachat.h \ + --replace __FILE__ '"${placeholder "out"}/include/deltachat.h"' + ''; +} diff --git a/nix/python-docs.nix b/nix/python-docs.nix new file mode 100644 index 0000000000..baef04d369 --- /dev/null +++ b/nix/python-docs.nix @@ -0,0 +1,15 @@ +{ pkgs, version, deltachat-python, deltachat-rpc-client }: +pkgs.stdenv.mkDerivation { + pname = "docs"; + inherit version; + src = pkgs.lib.cleanSource ../.; + buildInputs = [ + deltachat-python + deltachat-rpc-client + pkgs.python3Packages.breathe + pkgs.python3Packages.sphinx-rtd-theme + ]; + nativeBuildInputs = [ pkgs.sphinx ]; + buildPhase = ''sphinx-build -b html -a python/doc/ dist/html''; + installPhase = ''mkdir -p $out; cp -av dist/html $out''; +} diff --git a/nix/wheel.nix b/nix/wheel.nix new file mode 100644 index 0000000000..3e84526417 --- /dev/null +++ b/nix/wheel.nix @@ -0,0 +1,28 @@ +{ pkgs, nix-filter, version, root }: +{ rpc-server, arch, binaryName ? "deltachat-rpc-server" }: +pkgs.stdenv.mkDerivation { + pname = "deltachat-rpc-server-${arch}-wheel"; + inherit version; + src = nix-filter.lib { + inherit root; + include = [ + "scripts/wheel-rpc-server.py" + "deltachat-rpc-server/README.md" + "LICENSE" + "Cargo.toml" + ]; + }; + nativeBuildInputs = [ + pkgs.python3 + pkgs.python3Packages.wheel + ]; + buildInputs = [ + rpc-server + ]; + buildPhase = '' + mkdir tmp + cp ${rpc-server}/bin/${binaryName} tmp/${binaryName} + python3 scripts/wheel-rpc-server.py ${arch} tmp/${binaryName} + ''; + installPhase = ''mkdir -p $out; cp -av deltachat_rpc_server-*.whl $out''; +} diff --git a/nix/win32-package.nix b/nix/win32-package.nix new file mode 100644 index 0000000000..ebaa3fc660 --- /dev/null +++ b/nix/win32-package.nix @@ -0,0 +1,66 @@ +{ pkgs, naersk, fenixPkgs, system, version }: +packageName: +let + pkgsWin32 = pkgs.pkgsCross.mingw32; + rustTarget = pkgsWin32.stdenv.hostPlatform.rust.rustcTarget; + toolchainWin = fenixPkgs.combine [ + fenixPkgs.stable.rustc + fenixPkgs.stable.cargo + fenixPkgs.targets.${rustTarget}.stable.rust-std + ]; + naerskWin = pkgs.callPackage naersk { + cargo = toolchainWin; + rustc = toolchainWin; + }; + + # Get rid of MCF Gthread library. + # See + # and + # for details. + # + # Use DWARF-2 instead of SJLJ for exception handling. + winCC = pkgsWin32.buildPackages.wrapCC ( + (pkgsWin32.buildPackages.gcc-unwrapped.override + ({ + threadsCross = { + model = "win32"; + package = null; + }; + })).overrideAttrs (oldAttr: { + configureFlags = oldAttr.configureFlags ++ [ + "--disable-sjlj-exceptions" + "--with-dwarf2" + ]; + }) + ); +in +naerskWin.buildPackage rec { + pname = packageName; + cargoBuildOptions = x: x ++ [ "--package" packageName ]; + inherit version; + strictDeps = true; + src = pkgs.lib.cleanSource ../.; + nativeBuildInputs = [ + pkgs.perl # Needed to build vendored OpenSSL. + ]; + depsBuildBuild = [ + winCC + ]; + buildInputs = [ + pkgsWin32.windows.pthreads + ]; + auditable = false; # Avoid cargo-auditable failures. + doCheck = false; # Disable test as it requires network access. + + CARGO_BUILD_TARGET = rustTarget; + TARGET_CC = "${winCC}/bin/${winCC.targetPrefix}cc"; + CARGO_BUILD_RUSTFLAGS = [ + "-C" + "linker=${TARGET_CC}" + "-L" + "native=${pkgsWin32.windows.pthreads}/lib" + ]; + + CC = "${winCC}/bin/${winCC.targetPrefix}cc"; + LD = "${winCC}/bin/${winCC.targetPrefix}cc"; +} diff --git a/nix/win64-package.nix b/nix/win64-package.nix new file mode 100644 index 0000000000..98197cb007 --- /dev/null +++ b/nix/win64-package.nix @@ -0,0 +1,45 @@ +{ pkgs, naersk, fenixPkgs, system, version }: +packageName: +let + pkgsWin64 = pkgs.pkgsCross.mingwW64; + rustTarget = pkgsWin64.stdenv.hostPlatform.rust.rustcTarget; + toolchainWin = fenixPkgs.combine [ + fenixPkgs.stable.rustc + fenixPkgs.stable.cargo + fenixPkgs.targets.${rustTarget}.stable.rust-std + ]; + naerskWin = pkgs.callPackage naersk { + cargo = toolchainWin; + rustc = toolchainWin; + }; +in +naerskWin.buildPackage rec { + pname = packageName; + cargoBuildOptions = x: x ++ [ "--package" packageName ]; + inherit version; + strictDeps = true; + src = pkgs.lib.cleanSource ../.; + nativeBuildInputs = [ + pkgs.perl # Needed to build vendored OpenSSL. + ]; + depsBuildBuild = [ + pkgsWin64.stdenv.cc + ]; + buildInputs = [ + pkgsWin64.windows.pthreads + ]; + auditable = false; # Avoid cargo-auditable failures. + doCheck = false; # Disable test as it requires network access. + + CARGO_BUILD_TARGET = rustTarget; + TARGET_CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; + CARGO_BUILD_RUSTFLAGS = [ + "-C" + "linker=${TARGET_CC}" + "-L" + "native=${pkgsWin64.windows.pthreads}/lib" + ]; + + CC = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; + LD = "${pkgsWin64.stdenv.cc}/bin/${pkgsWin64.stdenv.cc.targetPrefix}cc"; +} diff --git a/scripts/wheel-rpc-server.py b/scripts/wheel-rpc-server.py index 4118ec4118..973dd853e9 100755 --- a/scripts/wheel-rpc-server.py +++ b/scripts/wheel-rpc-server.py @@ -20,86 +20,6 @@ def metadata_contents(version): """ -def build_source_package(version, filename): - with tarfile.open(filename, "w:gz") as pkg: - - def pack(name, contents): - contents = contents.encode() - tar_info = tarfile.TarInfo(f"deltachat_rpc_server-{version}/{name}") - tar_info.mode = 0o644 - tar_info.size = len(contents) - pkg.addfile(tar_info, BytesIO(contents)) - - pack("PKG-INFO", metadata_contents(version)) - pack( - "pyproject.toml", - f"""[build-system] -requires = ["setuptools==68.2.2", "pip"] -build-backend = "setuptools.build_meta" - -[project] -name = "deltachat-rpc-server" -version = "{version}" - -[project.scripts] -deltachat-rpc-server = "deltachat_rpc_server:main" -""", - ) - pack( - "setup.py", - f""" -import sys -from setuptools import setup, find_packages -from distutils.cmd import Command -from setuptools.command.install import install -from setuptools.command.build import build -import subprocess -import platform -import tempfile -from zipfile import ZipFile -from pathlib import Path -import shutil - - -class BuildCommand(build): - def run(self): - tmpdir = tempfile.mkdtemp() - subprocess.run( - [ - sys.executable, - "-m", - "pip", - "download", - "--no-input", - "--timeout", - "1000", - "--platform", - "musllinux_1_1_" + platform.machine(), - "--only-binary=:all:", - "deltachat-rpc-server=={version}", - ], - cwd=tmpdir, - ) - - wheel_path = next(Path(tmpdir).glob("*.whl")) - with ZipFile(wheel_path, "r") as wheel: - exe_path = wheel.extract("deltachat_rpc_server/deltachat-rpc-server", "src") - Path(exe_path).chmod(0o700) - wheel.extract("deltachat_rpc_server/__init__.py", "src") - - shutil.rmtree(tmpdir) - return super().run() - - -setup( - cmdclass={{"build": BuildCommand}}, - package_data={{"deltachat_rpc_server": ["deltachat-rpc-server"]}}, -) -""", - ) - pack("src/deltachat_rpc_server/__init__.py", "") - - def build_wheel(version, binary, tag, windows=False): filename = f"deltachat_rpc_server-{version}-{tag}.whl" @@ -168,23 +88,19 @@ def main(): with Path("Cargo.toml").open("rb") as fp: cargo_manifest = tomllib.load(fp) version = cargo_manifest["package"]["version"] - if sys.argv[1] == "source": - filename = f"deltachat_rpc_server-{version}.tar.gz" - build_source_package(version, filename) + arch = sys.argv[1] + executable = sys.argv[2] + tags = arch2tags[arch] + + if arch in ["win32", "win64"]: + build_wheel( + version, + executable, + f"py3-none-{tags}", + windows=True, + ) else: - arch = sys.argv[1] - executable = sys.argv[2] - tags = arch2tags[arch] - - if arch in ["win32", "win64"]: - build_wheel( - version, - executable, - f"py3-none-{tags}", - windows=True, - ) - else: - build_wheel(version, executable, f"py3-none-{tags}") + build_wheel(version, executable, f"py3-none-{tags}") main()