
在 macOS 上从源码编译 Hasura GraphQL Engine基于 brew 与 GHC 9.4.5 的完整实战指南【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine本篇指南完整复现 Hasura GraphQL Engine 开源仓库graphql-engine在 macOS 上的源码编译流程从 ghcup 安装 Haskell 工具链、brew 安装全部 C 语言依赖、构建 Console 前端资源、配置 Cabal 项目文件到最终产出graphql-engine可执行文件。读完本文你将能在一台全新的 macOS 上独立完成整个构建链路并理解版本号烘焙、前端资源加载等关键机制在源码中的实现方式。本文以仓库文档 server/COMPILING-ON-MACOS.md 为骨架并结合仓库内相关源码与配置文件进行深度印证。一、构建前置说明Homebrew 前缀路径整个编译流程的难点在于graphql-engine 依赖大量通过 brew 安装的 C 库libpq、unixodbc、openssl、libffi 等而 Haskell 的 Cabal 构建系统默认无法找到它们需要显式地通过路径配置让 Cabal 感知这些依赖。文档中的命令统一使用/opt/homebrew作为 Homebrew 安装前缀但你的机器上前缀可能不同较老版本的 Homebrew 通常安装到/usr/local。请先执行下面命令确认brew --prefix如果输出不是/opt/homebrew请将本文以及下文所有命令与配置中的/opt/homebrew一律替换为brew --prefix的实际输出路径。这一点若不注意后续的extra-include-dirs与extra-lib-dirs配置将指向不存在的目录Cabal 解析阶段就会直接失败。二、第一步安装 GHC 9.4.5 与 cabal-installghcup首先通过 ghcup 安装指定版本的 Haskell 工具链使用 ghcup 安装ghc-9.4.5使用 ghcup 安装cabal-install建议安装 3.x 较新版本以便支持后续构建所需的语法特性。安装完成后可用以下命令校验ghc --version cabal --version需要注意当前仓库根目录的 cabal.project以及 cabal/dev-sh.project中with-compiler已指向更新的编译器版本如ghc-9.14.1。因此本地编译前应核对所选 project 文件中的with-compiler与你实际安装的 GHC 版本是否一致避免 Cabal 报 cannot find compiler 类错误。三、第二步用 brew 安装全部系统依赖执行以下命令一次性安装构建所需的全部依赖brew install google-cloud-sdk \ node16 \ openssl \ unixodbc \ libpq \ libffi \ microsoft/mssql-release/mssql-tools18 \ direnv \ coreutils各依赖在构建链中的作用大致如下依赖用途google-cloud-sdkBigQuery 数据源相关的 SDK部分测试与功能需要node16构建 Console 前端资源nx/webpack 工具链opensslpostgresql-libpq等包的 TLS 依赖配置中需要其 include/lib 目录unixodbcODBC 数据源支持odbc包libpqPostgreSQL 客户端库postgresql-libpq与pg-client的核心依赖libffiPythoncffi及部分 Haskell 包的 C 依赖Python 构建时需其 pkgconfigmssql-tools18SQL Server 数据源的连接工具direnv开发环境变量管理工具coreutilsGNU coreutils部分构建脚本依赖其行为3.1 将依赖加入 PATH随后将这些工具加入 shell 环境以 zsh 为例echo export PATH/opt/homebrew/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/bin:$PATH ~/.zshrc echo export PATH/opt/homebrew/opt/openssl1.1/bin:$PATH ~/.zshrc echo export PATH/opt/homebrew/opt/node16/bin:$PATH ~/.zshrc echo export PATH/opt/homebrew/opt/libpq/bin:$PATH ~/.zshrc同样地如果brew --prefix输出不是/opt/homebrew请同步替换以上路径。执行后source ~/.zshrc或新开终端使其生效。提示如果你是在已有环境上重新执行这些步骤以更新 Mac构建可能因旧缓存失效而失败此时需先执行cabal clean清理后再继续。四、第三步构建 Console 前端资源server-build:cegraphql-engine 的可执行文件默认会将 Console控制台前端资源打包进服务因此编译前必须先在 frontend 目录下构建前端产物cd frontend npm ci npm run server-build:ce cd ..其中npm ci依据 frontend/package.json 的锁文件安装精确版本的依赖server-build:ce对应 package.json 中的server-build:ce: nx run console-ce:build-server-assets即通过 Nx 构建 CECommunity Edition控制台的 server assets。文档特别提醒这一步可能需要 python2 已安装且位于$PATH中部分较老的前端构建工具链依赖 python2。如果你的机器上缺少 python2可考虑用pyenv安装后加入 PATH再重试。若你构建的是 Enterprise/Pro 版本可对照 scripts/make/frontend.mk 中的目标使用server-build:ee对应命令。五、第四步安装 Python 环境测试依赖源码编译本身不依赖 Python但仓库的集成测试体系pytest需要一套 Python 环境。按文档执行export PKG_CONFIG_PATH/opt/homebrew/opt/libffi/lib/pkgconfig export LDFLAGS-L/opt/homebrew/opt/openssl1.1/lib export CPPFLAGS-I/opt/homebrew/opt/openssl1.1/include cd server python3 -m venv .python-venv source .python-venv/bin/activate pip3 install -r tests-py/requirements.txt (cd tests-py/remote_schemas/nodejs npm ci)说明PKG_CONFIG_PATH指向 libffi 的 pkgconfig 目录让 Python 生态中的 cffi 等包能正确找到 libffiLDFLAGS/CPPFLAGS指向 openssl供需要链接 OpenSSL 的 Python 包使用依赖清单位于 server/tests-py/requirements.txt集成测试使用的 Node.js remote schema 示例依赖在 server/tests-py/remote_schemas/nodejs需要单独npm ci。六、第五步配置 Cabal 以定位 C 依赖这是整个流程中最容易出错的一步。Cabal 默认不会自动搜索 brew 安装的 C 库必须通过 project 文件中的package段为相关 Haskell 包指定额外的 include 与 lib 搜索目录。6.1 追加 package 配置将以下内容追加到cabal/dev-sh.project.local文件末尾同样记得替换/opt/homebrewpackage odbc extra-include-dirs: /opt/homebrew/opt/unixodbc/include extra-lib-dirs: /opt/homebrew/opt/unixodbc/lib package postgresql-libpq extra-include-dirs: /opt/homebrew/opt/libpq/include /opt/homebrew/opt/openssl/include extra-lib-dirs: /opt/homebrew/opt/libpq/lib /opt/homebrew/opt/openssl/lib package pg-client extra-include-dirs: /opt/homebrew/opt/libpq/include /opt/homebrew/opt/openssl/include extra-lib-dirs: /opt/homebrew/opt/libpq/lib /opt/homebrew/opt/openssl/lib这三个 package 分别是odbcODBC 数据库驱动封装依赖 unixodbc 头文件与动态库postgresql-libpqPostgreSQL libpq 的 Haskell 绑定依赖 libpq 与 opensslpg-clientgraphql-engine 仓库内部的 PostgreSQL 客户端封装库同样直接依赖 libpq 与 openssl。你可以直接在仓库 cabal/dev-sh.project.local 中看到该文件的原貌它同时包含debug-info、executable-dynamic: True、library-vanilla: False等针对本地开发优化的全局配置末尾三段正是上述 C 依赖路径配置——这也印证了文档描述与仓库现状的一致性若你的 brew 前缀不同仍需手动改写这几段。6.2 启用 project.local 配置将整个cabal/dev-sh.project.local的内容复制粘贴到cabal.project.local或者直接创建符号链接ln -s cabal/dev-sh.project.local cabal.project.local两种方式的取舍复制粘贴可以在cabal.project.local中继续叠加本地项目的package graphql-engine覆盖配置——如果你打算修改 graphql-engine 源码本身推荐这种方式符号链接简单省事适合按原样编译的场景不需要对代码做任何改动。注意cabal.project.local是 Cabal 默认读取的本地覆盖文件会被 Cabal 自动加载若你通过--project-file指定了其他 project 文件例如 scripts/dev.sh 使用的cabal/dev-sh.project则对应的.local文件规则需按该工具的既有约定来放置。七、第六步写入版本号到 server/CURRENT_VERSIONgraphql-engine 会在编译期把版本号烘焙进二进制。这一步是很多新手容易跳过的但跳过会直接导致编译失败。echo 2.13.0 server/CURRENT_VERSION2.13.0仅为示例请替换为你要构建的实际版本号例如仓库 releases 目录中存在的版本。7.1 源码级原理版本号如何被读取在 server/src-lib/Hasura/Server/Version.hs 中currentVersion通过 Template Haskell 在编译期读取该文件currentVersion :: Version currentVersion fromText $ T.dropWhileEnd ( \n) $ T.pack $( do versionFileName - makeRelativeToProject CURRENT_VERSION addDependentFile versionFileName ... runIO (readFile versionFileName onException error noFileErr) stringE )关键细节makeRelativeToProject CURRENT_VERSION定位仓库server/目录下的版本文件addDependentFile把该文件登记为编译依赖使缓存场景下文件变化也能触发正确重编译这也是 server/graphql-engine.cabal 第 13-21 行将CURRENT_VERSION列入extra-source-files的原因注释明确引用了 cabal 的 issue #4746文件不存在时会抛出提示信息指引开发者先执行echo 12345 .../server/CURRENT_VERSION。版本字符串会被解析为三种形态之一Version.hs形态判定示例输出VersionRelease能按 SemVer 解析如2.13.0v2.13.0VersionCE以-ce结尾原样输出VersionDev其余无法解析的字符串如12345原样输出7.2 版本号的两种用途版本号在编译出的二进制中承担两个作用graphql-engine --version的输出内容Console 前端资源的 CDN 地址生成如果运行时未通过--console-assets-dir指定本地编译的前端资源目录服务器将依据版本号映射到 CDN 上的 Console 资源。映射逻辑见 server/src-lib/Hasura/Server/Version.hs 的versionToAssetsVersion正式发布版本会映射为versioned/v2.13这类路径并依据预发布标识推断stable/beta等发布通道开发版本则映射为versioned/文本。因此若你构建的是未发布版本却希望使用 CDN Console版本号的形态会直接影响资源能否命中想要加载本地构建的 Console 资源则应使用--console-assets-dir指向第四步生成的 assets 目录。7.3 本地开发使用的魔术版本号值得一提的是仓库的 scripts/dev.sh 在本地开发时统一写入12345作为版本号其注释说明这是有意为之该数字保证不触发无谓重编译并且在集成测试的版本测试中被显式忽略。如果你仅想编译一个可运行的服务而不关心版本号写入12345与写入真实版本号在构建层面同样有效。八、第七步正式编译完成以上全部准备后开始构建cabal update cabal build exe:graphql-engine -j4cabal update拉取 Hackage 包索引首次构建必须cabal build exe:graphql-engine -j4以 4 路并行编译 server 主程序产物为graphql-engine可执行文件。构建产物默认位于 Cabal 的 dist-newstyle 目录下可通过cabal list-bin exe:graphql-engine查看确切路径。这是首次构建Haskell 依赖树庞大请预留充足时间与磁盘空间。九、构建后的验证与运行编译完成后可先验证版本输出$(cabal list-bin exe:graphql-engine) --version启动服务以本地 PostgreSQL 为例仓库根目录 docker-compose.yaml 提供了配套数据库编排$(cabal list-bin exe:graphql-engine) serve如需加载本地编译的 Console 资源可添加--console-assets-dir指向 frontend 构建产物目录否则服务器会依据CURRENT_VERSION从 CDN 拉取对应版本的 Console 资源详见 server/src-lib/Hasura/Server/App.hs 附近的静态资源服务逻辑。十、常见问题排查速查现象原因与处理cabal报找不到 GHC未安装 ghc-9.4.5或 project 文件with-compiler与实际安装版本不一致链接阶段找不到libpq/odbc未正确配置 cabal/dev-sh.project.local 中的extra-include-dirs/extra-lib-dirs或/opt/homebrew前缀与实际不符TH 阶段报DEAR HASURIAN错误未创建server/CURRENT_VERSION文件按提示写入版本号即可参见 Version.hs 中的错误信息前端构建失败提示 python2按文档第四步说明安装 python2 并加入$PATH更新环境后构建异常先执行cabal clean清理旧缓存再重新构建结语通过 ghcup brew Cabal 的三段式配合你可以在 macOS 上完整构建 Hasura GraphQL Engineghcup 提供 Haskell 工具链brew 补齐全部 C 依赖而cabal/dev-sh.project.local则充当连接两者的桥梁。理解CURRENT_VERSION的编译期烘焙机制server/src-lib/Hasura/Server/Version.hs与 Console 资源的加载策略能帮助你在构建自有版本、调试 Console 时少走弯路。建议以本文配合仓库文档 server/COMPILING-ON-MACOS.md 与 scripts/dev.sh 一起阅读后者封装了本地开发所需的完整环境编排。【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考