Haskell Stack构建不依赖项目库的可执行文件如何避免重编译?
问题原因
重编译问题的根源有三个:
- 构建基准测试时指定了自定义的
--work-dir,但运行checkresult时没有复用同一个工作目录,Stack默认使用.stack-work作为工作目录,两套工作目录的构建产物完全隔离,自然需要重新编译所有内容 - 传递
--ghc-options时使用了全局生效的写法,该参数会修改整个项目所有组件的编译哈希,哪怕和参数无关的组件也会被标记为需要重新构建 - 部分Stack版本默认开启了全组件构建,只要在项目根目录运行构建命令,哪怕你只指定了单个组件,也会尝试构建所有项目组件,包括你不需要的主库
解决方案
方案1:统一工作目录(最推荐)
将工作目录路径抽成变量,全程复用同一套构建环境,同时限制GHC参数仅作用于基准测试组件,避免影响其他组件的编译哈希,修改后的脚本如下:
#!/bin/bash if [[ "$1" = "verbose" ]]; then WORK_DIR=".verbose-stack-dir/" # 仅给基准测试组件传递GHC参数,不影响其他组件 EXTRA_BUILD_ARGS="--ghc-options mypkg:bench:benchmark=-DMYPKG_VERBOSE" else WORK_DIR=".nonverbose-stack-dir/" EXTRA_BUILD_ARGS="" fi echo "Building the benchmark" stack --work-dir "$WORK_DIR" build -j 4 $EXTRA_BUILD_ARGS mypkg:bench:benchmark echo "Checking results" # 复用相同工作目录,关闭全组件构建,仅处理目标可执行文件 stack --work-dir "$WORK_DIR" run --no-all-components mypkg:exe:checkresult
方案2:单独构建校验工具
如果你确实需要分开使用不同的工作目录,可以在运行校验工具时指定仅构建目标组件,跳过同项目其他无关组件:
stack run --no-all-components mypkg:exe:checkresult
该命令只会构建checkresult及其显式声明的依赖,不会处理同项目的主库等无关组件。
永久配置优化
可以在项目的stack.yaml中添加如下配置,默认关闭全组件构建,避免每次手动加参数:
build: all-components: false
内容的提问来源于stack exchange,提问作者fakedrake
相关产品推荐
相关产品推荐

