如何配置Stack向GHC及CPP预处理器传递自定义编译标志?
我的Haskell代码包含以下条件编译逻辑:
#if FLAG bogus1 x = x + 1 #else bogus2 x = x + 2 #endif
我尝试在package.yaml中配置编译标志传递给GHC,最初的配置如下(无效,仍编译bogus2,且收到警告提示应使用cpp-options替代ghc-options):
executables: my_maim: main: Main.hs source-dirs: app ghc-options: - "-DFLAG" - -main-is Main dependencies: - MyPackage
修改为以下配置后,执行stack build仍无法传递正确标志,但使用命令stack build -ghc-options --DFLAG可正常生效(编译bogus1)。请问哪里配置错误?如何正确设置Stack传递所需标志?
你的配置存在两个关键问题,修正后即可正常生效:
1. 移除cpp-options中选项的冗余引号
在package.yaml中配置cpp-options时,"-DFLAG"的引号是多余的。YAML会将带引号的字符串作为完整参数传递,导致GHC收到的是"-DFLAG"而非-DFLAG,宏FLAG并未被正确定义。只需去掉引号,直接写-DFLAG即可。
2. 确保启用CPP扩展
Haskell默认不启用C预处理器(CPP),如果代码中没有通过{-# LANGUAGE CPP #-}编译指令显式启用,必须在package.yaml中添加CPP扩展配置,否则GHC会忽略所有#if/#else/#endif预处理指令。
正确配置示例
方式1:为目标可执行文件单独配置
executables: my_maim: main: Main.hs source-dirs: app extensions: - CPP # 启用CPP扩展 cpp-options: - -DFLAG # 去掉冗余引号 ghc-options: - -main-is Main dependencies: - MyPackage
方式2:全局启用CPP扩展(适用于整个项目)
如果项目中多个模块需要使用CPP,可以在package.yaml顶层配置全局扩展:
default-extensions: - CPP # 全局启用CPP executables: my_maim: main: Main.hs source-dirs: app cpp-options: - -DFLAG ghc-options: - -main-is Main dependencies: - MyPackage
命令行方式生效的原因
stack build -ghc-options --DFLAG会被Stack自动转换为GHC可识别的-optP-DFLAG参数(传递给预处理器的宏定义),同时如果你的代码中已经通过{-# LANGUAGE CPP #-}启用了扩展,就能正确触发条件编译。
内容的提问来源于stack exchange,提问作者user2506946

