在需要LANGUAGE CPP的模块上运行ghci

时间:2013-10-27 19:35:53

标签: c++ haskell ghc cabal ghci

我遇到了这一系列命令的问题:

wget http://hackage.haskell.org/package/github-0.7.1/github-0.7.1.tar.gz
tar zxf github-0.7.1.tar.gz
cd github-0.7.1
ghci samples/Users/ShowUser.hs

我得到的错误是:

Github/Private.hs:142:0:
     error: missing binary operator before token "("

Github/Private.hs:148:0:
     error: missing binary operator before token "("
phase `C pre-processor' failed (exitcode = 1)

那是因为模块Github / Private.hs在两个地方使用cpp指令:

#if MIN_VERSION_http_conduit(1, 9, 0)
    successOrMissing s@(Status sci _) hs cookiejar
#else
    successOrMissing s@(Status sci _) hs
#endif
      | (200 <= sci && sci < 300) || sci == 404 = Nothing
#if MIN_VERSION_http_conduit(1, 9, 0)
      | otherwise = Just $ E.toException $ StatusCodeException s hs cookiejar
#else
      | otherwise = Just $ E.toException $ StatusCodeException s hs
#endif

ghci似乎对这些CPP指令感到窒息。但是,cabal install成功编译并安装了程序包。使用ghci -XCPP无济于事。

我的问题是:如何使用此程序包的samples目录中的库代码,使用ghci运行示例程序(即Github目录中的程序)?

我想尝试调整示例程序和库代码,因此我想在ghci中运行所有内容。

有效的一件事是:

cabal install
cd samples
ghci Users/ShowUser.hs

但是,我再次不必安装库代码来测试它。

2 个答案:

答案 0 :(得分:11)

以下命令有效:

ghci -optP-include -optPdist/build/autogen/cabal_macros.h samples/Users/ShowUser.hs

它告诉C预处理器读取文件dist/build/autogen/cabal_macros.h。此文件由cabal build生成,但您可以在preprocessing步骤后中止该文件:

Resolving dependencies...
Configuring github-0.7.1...
Building github-0.7.1...
Preprocessing library github-0.7.1...
[ 1 of 24] Compiling Github.Data.Definitions ( Github/Data/Definitions.hs,    dist/build/Github/Data/Definitions.o )
^C

如果您希望在该目录中启动ghci时自动设置这些选项,请使用以下内容创建.ghci文件:

:set -optP-include -optPdist/build/autogen/cabal_macros.h

答案 1 :(得分:6)

问题不在于C预处理器本身,但是MIN_VERSION_*宏是由cabal在构建时生成的,因此您不会在GHCi中获取它们。如果您只想在不安装库的情况下使用库,那么阻力最小的路径就是注释掉宏,以及CPP条件的分支,这些分支与您当前拥有的http-conduit版本不匹配(如有疑问,请查看ghc-pkg list)。


稍微有点原则性的黑客攻击将使用CPP检查您是否使用cabal进行安装。假设http_conduit >= 1.9.0可能如下所示:

#ifdef CABAL
#  if MIN_VERSION_http_conduit(1, 9, 0)
    successOrMissing s@(Status sci _) hs cookiejar
#  else
    successOrMissing s@(Status sci _) hs
#  endif
      | (200 <= sci && sci < 300) || sci == 404 = Nothing
#  if MIN_VERSION_http_conduit(1, 9, 0)
      | otherwise = Just $ E.toException $ StatusCodeException s hs cookiejar
#  else
      | otherwise = Just $ E.toException $ StatusCodeException s hs
#  endif
#else
    successOrMissing s@(Status sci _) hs cookiejar
      | (200 <= sci && sci < 300) || sci == 404 = Nothing
      | otherwise = Just $ E.toException $ StatusCodeException s hs cookiejar
#endif

考虑到你的用例,我不认为额外的步骤是值得的。


为了完整起见:this answer解释了如何在GHCi中使用cabal宏。但是,这样做至少需要运行cabal build一次。