diff --git a/.github/workflows/prebuilt-tdlib.yml b/.github/workflows/prebuilt-tdlib.yml index cd870fc..0c43c60 100644 --- a/.github/workflows/prebuilt-tdlib.yml +++ b/.github/workflows/prebuilt-tdlib.yml @@ -22,6 +22,7 @@ jobs: build-linux-x86_64: name: 'Build TDLib / Linux x86_64 glibc' runs-on: ubuntu-22.04 + if: ${{ false }} steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v27 @@ -35,9 +36,34 @@ jobs: with: name: tdlib-linux-x86_64-glibc path: ${{ env.TO_UPLOAD }} + build-linux-arm64: + name: 'Build TDLib / Linux arm64 glibc (cross)' + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - uses: goto-bus-stop/setup-zig@v2 + with: + version: '0.13.0' + - uses: cachix/install-nix-action@v27 + with: + nix_path: nixpkgs=channel:nixos-unstable + - name: Build TDLib + run: | + cd packages/prebuilt-tdlib/ci + ./build-linux.sh ${{ inputs.tdlib }} aarch64-linux-gnu.2.22 + # - name: Setup tmate session + # uses: mxschmitt/action-tmate@v3 + # if: failure() + # with: + # limit-access-to-actor: true + - uses: actions/upload-artifact@v4 + with: + name: tdlib-linux-arm64 + path: ${{ env.TO_UPLOAD }} build-macos-x86_64: name: 'Build TDLib / macOS x86_64' runs-on: macos-13 + if: ${{ false }} steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v27 @@ -54,6 +80,7 @@ jobs: build-macos-arm64: name: 'Build TDLib / macOS arm64' runs-on: macos-14 + if: ${{ false }} steps: - uses: actions/checkout@v4 - uses: cachix/install-nix-action@v27 @@ -90,6 +117,7 @@ jobs: build-windows-x86_64: name: 'Build TDLib / Windows x86_64' runs-on: windows-2019 + if: ${{ false }} steps: - uses: actions/checkout@v4 with: @@ -126,7 +154,11 @@ jobs: test: name: 'Test / ${{ matrix.v.bin }} / ${{ matrix.v.os }}' - needs: [build-linux-x86_64, build-macos, build-windows-x86_64] + needs: + - build-linux-x86_64 + - build-linux-arm64 + - build-macos + - build-windows-x86_64 runs-on: ${{ matrix.v.os }} strategy: fail-fast: false diff --git a/packages/prebuilt-tdlib/ci/build-linux.sh b/packages/prebuilt-tdlib/ci/build-linux.sh index 90ba87d..2783091 100755 --- a/packages/prebuilt-tdlib/ci/build-linux.sh +++ b/packages/prebuilt-tdlib/ci/build-linux.sh @@ -10,7 +10,7 @@ fi set -ex -nix-build tdlib-linux.nix -v --argstr rev "$_tdlib" --argstr target "$_target" +nix-build tdlib-linux-aarch64.nix -v --argstr rev "$_tdlib" --argstr target "$_target" mkdir to-upload cp -L ./result/lib/libtdjson.so to-upload/libtdjson.so diff --git a/packages/prebuilt-tdlib/ci/tdlib-linux-aarch64.nix b/packages/prebuilt-tdlib/ci/tdlib-linux-aarch64.nix new file mode 100644 index 0000000..c405072 --- /dev/null +++ b/packages/prebuilt-tdlib/ci/tdlib-linux-aarch64.nix @@ -0,0 +1,76 @@ +{ target, rev }: +let + # zig-env = import ./zig-stdenv.nix { + # pkgs = pkgs-native; + # target = "aarch64-unknown-linux-gnu"; + # zig-target = target; + # }; + # pkgs = if lib.strings.hasPrefix "x86_64" target then pkgs-native else pkgs-native.pkgsCross.aarch64-multiplatform; + # stdenv = if lib.strings.hasPrefix "x86_64" target then pkgs-native.stdenv else zig-env.stdenv; + # inherit (zig-env) pkgs; + pkgs = if builtins.substring 0 7 target == "aarch64" + then import { crossSystem.config = "aarch64-unknown-linux-gnu"; } + else import {}; + inherit (pkgs) lib stdenv; + zig-toolchain = import ./zig-toolchain.nix { inherit target; pkgs = pkgs.buildPackages.buildPackages; }; + zlib = pkgs.callPackage ./zlib-zig.nix { inherit zig-toolchain; }; + openssl = pkgs.callPackage ./openssl-zig.nix { inherit zig-toolchain; }; +in +# Based on https://github.com/NixOS/nixpkgs/blob/af51e23ce535b1bfa8484021ff3913d876e09082/pkgs/development/libraries/tdlib/default.nix +stdenv.mkDerivation { + pname = "tdlib"; + version = "0.0"; + + src = builtins.fetchTarball "https://github.com/tdlib/td/archive/${rev}.tar.gz"; + + buildInputs = [ openssl zlib ]; + nativeBuildInputs = with pkgs.buildPackages; [ cmake gperf ]; + + preConfigure = '' + export CC=${pkgs.buildPackages.stdenv.cc}/bin/cc + export CXX=${pkgs.buildPackages.stdenv.cc}/bin/c++ + ls ${pkgs.buildPackages.openssl} + mkdir native-build && cd native-build + cmake -DOPENSSL_ROOT_DIR=${pkgs.buildPackages.openssl} \ + -DZLIB_INCLUDE_DIR=${pkgs.buildPackages.zlib}/include \ + -DZLIB_LIBRARY=${pkgs.buildPackages.zlib}/lib/libz.a \ + -DOPENSSL_USE_STATIC_LIBS=FALSE \ + .. + cmake --build . --target prepare_cross_compiling + cd .. + exit + '' + zig-toolchain.env; + + patches = [ ./tdlib-zig.patch ]; + + cmakeFlags = [ + "-DCMAKE_BUILD_TYPE=Release" + "-DOPENSSL_USE_STATIC_LIBS=TRUE" + "-DZLIB_USE_STATIC_LIBS=TRUE" + "-DCMAKE_SYSTEM_NAME=Linux" + "-DCMAKE_CROSSCOMPILING=TRUE" + ]; + + buildPhase = '' + cmake --build . --target tdjson -j $NIX_BUILD_CORES + ''; + + installPhase = '' + runHook preInstall + mkdir -p "$out"/lib + cp -L ./libtdjson.so "$out"/lib/ + runHook postInstall + ''; + + # https://github.com/tdlib/td/issues/1974 + postPatch = '' + substituteInPlace CMake/GeneratePkgConfig.cmake \ + --replace 'function(generate_pkgconfig' \ + 'include(GNUInstallDirs) + function(generate_pkgconfig' \ + --replace '\$'{prefix}/'$'{CMAKE_INSTALL_LIBDIR} '$'{CMAKE_INSTALL_FULL_LIBDIR} \ + --replace '\$'{prefix}/'$'{CMAKE_INSTALL_INCLUDEDIR} '$'{CMAKE_INSTALL_FULL_INCLUDEDIR} + '' + lib.optionalString (stdenv.isDarwin && stdenv.isAarch64) '' + sed -i "/vptr/d" test/CMakeLists.txt + ''; +} diff --git a/packages/prebuilt-tdlib/ci/zig-stdenv.nix b/packages/prebuilt-tdlib/ci/zig-stdenv.nix new file mode 100644 index 0000000..64ee838 --- /dev/null +++ b/packages/prebuilt-tdlib/ci/zig-stdenv.nix @@ -0,0 +1,107 @@ +# https://gist.github.com/Cloudef/acb74ff9e36ab41709479240596ab501 +{ pkgs ? import {}, lib ? pkgs.lib, stdenv ? pkgs.stdenv, zig ? pkgs.zig, static ? false, target, zig-target }: + +with lib; +with builtins; + +let + zig-stdenv = let + write-zig-wrapper = cmd: pkgs.writeShellScript "zig-${cmd}" ''${zig}/bin/zig ${cmd} "$@"''; + zig-cc = write-zig-wrapper "cc"; + zig-cxx = write-zig-wrapper "c++"; + zig-ar = write-zig-wrapper "ar"; + zig-ranlib = write-zig-wrapper "ranlib"; + zig-dlltool = write-zig-wrapper "dlltool"; + zig-lib = write-zig-wrapper "lib"; + + # XXX: Consider LLVM binutils instead? + bintools = pkgs.bintoolsNoLibc; + symlinks = [ + { name = "bin/clang"; path = zig-cc; } + { name = "bin/clang++"; path = zig-cxx; } + { name = "bin/cc"; path = zig-cc; } + { name = "bin/c++"; path = zig-cxx; } + { name = "bin/ld"; path = zig-cc; } + { name = "bin/gold"; path = zig-cc; } + { name = "bin/ar"; path = zig-ar; } + { name = "bin/ranlib"; path = zig-ranlib; } + { name = "bin/dlltool"; path = zig-dlltool; } + { name = "bin/lib"; path = zig-lib; } + ] ++ map (x: { name = "bin/${x}"; path = "${bintools}/bin/${x}"; }) [ + "addr2line" "c++filt" "elfedit" "gprof" "gprofng" "nlmconv" "nm" "as" + "objcopy" "objdump" "readelf" "size" "strings" "windmc" "windres" "strip" + ]; + + zig-toolchain = pkgs.linkFarm "zig-toolchain" (symlinks + ++ map (x: let y = last (splitString "/" x.name); in { name = "bin/${target}-${y}"; path = y; }) symlinks) // { + inherit (pkgs.llvmPackages.libclang) version; + pname = "zig-toolchain"; + isClang = true; + libllvm.out = ""; + }; + + # Bunch of overrides to make sure we don't ever start bootstrapping another cross-compiler + overrides = self: super: let + to-override-set = x: genAttrs x (x: zig-toolchain); + llvmPackages = to-override-set [ "clang" "libclang" "lld" "llvm" "libllvm" "compiler-rt" "libunwind" "libstdcxx" "libcxx" "libcxxapi" "openmp" ]; + in (to-override-set [ + "gcc" "libgcc" "glibc" "bintools" "bintoolsNoLibc" "binutils" "binutilsNoLibc" + "gccCrossStageStatic" "preLibcCrossHeaders" "glibcCross" "muslCross" "libcCross" + ]) // { + inherit llvmPackages; + inherit (llvmPackages) clang libclang lld llvm libllvm libunwind libstdcxx libcxx libcxxapi openmp; + gccForLibs = null; # also disables --gcc-toolchain passed to compiler + }; + + cross0 = import pkgs.path { + crossSystem.config = target; + localSystem.config = pkgs.buildPlatform.config; + crossOverlays = [overrides]; + }; + + static-stdenv-maybe = x: if static then cross0.makeStatic x else x; + + zig-stdenv0 = static-stdenv-maybe (cross0.overrideCC cross0.stdenv (cross0.wrapCCWith rec { + inherit (pkgs) gnugrep coreutils; + cc = zig-toolchain; libc = cc; libcxx = cc; + bintools = cross0.wrapBintoolsWith { inherit libc gnugrep coreutils; bintools = cc; }; + # XXX: -march is not compatible + # https://github.com/ziglang/zig/issues/4911 + extraBuildCommands = '' + substituteInPlace $out/nix-support/add-local-cc-cflags-before.sh --replace "${target}" "${zig-target}" + sed -i 's/-march[^ ]* *//g' $out/nix-support/cc-cflags-before + ''; + })); + + # Aaand .. finally our final stdenv :) + in zig-stdenv0.override { + inherit overrides; + # XXX: Zig doesn't support response file. Nixpkgs wants to use this for clang + # while zig cc is basically clang, it's still not 100% compatible. + # Probably should report this as a bug to zig upstream though. + preHook = '' + ${cross0.stdenv.preHook} + export NIX_CC_USE_RESPONSE_FILE=0 + export ZIG_LOCAL_CACHE_DIR="$TMPDIR/zig-cache-${target}" + export ZIG_GLOBAL_CACHE_DIR="$ZIG_LOCAL_CACHE_DIR" + ''; + }; + + cross = (import pkgs.path { + crossSystem.config = target; + localSystem.config = pkgs.buildPlatform.config; + crossOverlays = [(self: super: { + stdenv = zig-stdenv; + # XXX: libsepol issue on darwin, should be fixed upstrem instead + libsepol = super.libsepol.overrideAttrs (old: { + nativeBuildInputs = with pkgs; old.nativeBuildInputs ++ optionals (stdenv.isDarwin) [ + (writeShellScriptBin "gln" ''${pkgs.coreutils}/bin/ln "$@"'') + ]; + }); + })]; + }); +in { + inherit target; + stdenv = zig-stdenv; + pkgs = cross; +} diff --git a/packages/prebuilt-tdlib/ci/zlib-zig.nix b/packages/prebuilt-tdlib/ci/zlib-zig.nix index 948b5cb..40443b0 100644 --- a/packages/prebuilt-tdlib/ci/zlib-zig.nix +++ b/packages/prebuilt-tdlib/ci/zlib-zig.nix @@ -2,13 +2,4 @@ (zlib.override { static = true; shared = false; }).overrideAttrs (final: prev: { preConfigure = prev.preConfigure + zig-toolchain.env; doCheck = false; - # preCheck = '' - # ls - # echo --- - # ldd ./minigzip - # ./minigzip - # echo START - # make check - # echo FINISH - # ''; })