Skip to content

Commit

Permalink
[wip] prebuilt-tdlib: crosscompile to Linux arm64
Browse files Browse the repository at this point in the history
  • Loading branch information
eilvelia committed Jul 17, 2024
1 parent d3580a4 commit b686e90
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 11 deletions.
34 changes: 33 additions & 1 deletion .github/workflows/prebuilt-tdlib.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion packages/prebuilt-tdlib/ci/build-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 76 additions & 0 deletions packages/prebuilt-tdlib/ci/tdlib-linux-aarch64.nix
Original file line number Diff line number Diff line change
@@ -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 <nixpkgs> { crossSystem.config = "aarch64-unknown-linux-gnu"; }
else import <nixpkgs> {};
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
'';
}
107 changes: 107 additions & 0 deletions packages/prebuilt-tdlib/ci/zig-stdenv.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# https://gist.github.com/Cloudef/acb74ff9e36ab41709479240596ab501
{ pkgs ? import <nixpkgs> {}, 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;
}
9 changes: 0 additions & 9 deletions packages/prebuilt-tdlib/ci/zlib-zig.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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
# '';
})

0 comments on commit b686e90

Please sign in to comment.