Skip to content

Haskell GHC 构建问题 #1

@Aleksanaa

Description

@Aleksanaa

一、主要现状

  1. Haskell 包组与版本定义

  2. 交叉编译与工具链讨论

  3. 相关组件说明

    • GHC:Haskell 的官方编译器
    • native-bignum:替代 GMP 的 Haskell 库
    • hadrian:替代 GNU Make 的构建系统
  4. GHC 后端方案

    • LLVM
    • NCG(用 Haskell 编写,目前不支持 LoongArch64)
    • Unregisterised(先编译成 C,再由 C 编译器处理;性能较低,用于 bootstrap)
  5. LoongArch64 支持与版本现状

    • GHC 从 9.6 起支持 LoongArch64,配合 LLVM 16 使用(需绕过 LLVM 15 限制并做适当改动,详见链接 1 中注释)。
    • Nixpkgs 中默认 GHC 版本为 9.6.6,在 staging-next 分支中已更新至 9.8.4
      haskellPackages: Stackage LTS 22 -> 23; ghc: 9.6.6 -> 9.8.4 NixOS/nixpkgs#371032
    • 当前 Nixpkgs 的 Haskell 构建方式:导入官方 bindist tarball,再编译源码(即上游包中的 -binary 流程)。
  6. 当前目标
    在 x86_64-linux Hydra 上,构建面向 LoongArch64 的 bindist tarball,并由 Infrastructure Team 上传至 tarball.nixos.org,以与其他受支持架构保持一致的本地构建流程。


二、交叉编译问题

  1. GHC 的三阶段构建流程

    • Configure 阶段 → Hadrian 构建:
      • stage0stage1stage2 三个阶段一次性完成
      • 输入的 Platform Triple 中,buildhost 都是本地架构,target 是目标架构(即输入 configure 的为 stage0 的 triple)
  2. Nixpkgs 中的 Platform Triple 差异

    • pkgsCross.loongarch64-linux.haskell.compilers.ghc984 三元组为 (x86_64, loongarch64, loongarch64)
    • GHC 期望的顺序应为 (build=x86_64, host=x86_64, target=loongarch64)
    • 因此,需要退一步使用:
      • pkgsCross.loongarch64-linux.pkgsBuildHost.haskell.compilers.ghc984
      • 或者 pkgsCross.loongarch64-linux.haskell.packages.ghc984.ghc
        (两者均未完全验证,但准备的 triple 满足 GHC 要求)
  3. 绕过libffi编译错误

    • libffi 在 stage0 提前介入,导致编译失败:
      • 阶段使用的 libffi 头文件期望 gcc 定义 __loongarch__,但此时的 gcc 尚未打好宏
      • 原因可能是 configureFlags 中传入的 libffi 来自 targetPlatform
    • 当前对策:使用ghc自带libffilibffi = null
  4. 示例 Derivation 片段
    libffi = null;且暂不开启 LLVM,启用 unregisterised:

    callPackage ../development/compilers/ghc/9.8.4.nix {
      bootPkgs = bb.packages.ghc963Binary;      # 以 GHC 9.6 binary 为 bootPkgs
      inherit (buildPackages.python3Packages) sphinx;
      inherit (buildPackages.darwin) xattr autoSignDarwinBinariesHook;
      buildTargetLlvmPackages = pkgsBuildTarget.llvmPackages_15;
      llvmPackages = pkgs.llvmPackages_15;
      useLLVM = false;
      libffi = null;
      enableUnregisterised = true;
    }

这样在haskell-packages.nix修改ghc 9.8.4理论上就可以开始编译。

  1. common-hadrian.nix 中的调整

    • 将默认 finalStage 从 stage1 改为 stage2
    • 判断条件为:
      stdenv.hostPlatform.canExecute stdenv.targetPlatform
      • stage1 通常可完成,能生成在 x86_64 上运行、可编译 LoongArch64 二进制的 GHC
      • 问题出在 stage2:后续重复构建时,无法正确“喂”入对应的工具链和库,导致 libs-install 和 stage2 阶段失败
  2. 问题归因与展望

    • 上游(456)暗示,直接交叉编译 GHC 主体存在困难
    • 龙芯社区已有成功案例,说明可能是构建流程或 Nixpkgs 假设不匹配所致
    • 解决此处问题,有望同时破解 RISC-V 平台的本地编译难题

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions