GHC 版本签入代码

GHC version check in code

我正在为 Alex 做贡献,它显然依赖于很多库,应该针对很多版本进行编译。

我需要使用仅在 GHC 7.6.1 中可用的函数来更好地处理错误。所以我想使用 #if ... 来导入所述函数,否则,我将以不同的方式处理错误。

我看过一些:

#if __GLASGOW_HASKELL__ >= 610
import Control.Exception ( bracketOnError )
#endif

所以我做到了:

#if __GLASGOW_HASKELL__ >= 761
import Text.Read ( readMaybe )
#endif

认为 761 是 GHC 版本 7.6.1 的别名,当我构建 cabal 包并尝试它时,即使我使用 [=38],该函数也没有被导入=]The Glorious Glasgow Haskell编译系统,版本7.8.4.

于是用程序试了一下,发现7.8.1__GLASGOW_HASKELL__中识别为708

{-# LANGUAGE CPP #-}
module Main where

#if __GLASGOW_HASKELL__ == 708
ver = "==708"
#else
ver = "/=708"
#endif

main = putStrLn $ ver

和运行它:

$ runhaskell if.hs
==708

我怎么知道我应该为 7.6.1 使用什么值,或者有更好的方法来处理这个问题吗?

阅读 fine documentation:

For version x.y.z of GHC, the value of __GLASGOW_HASKELL__ is the integer xyy (if y is a single digit, then a leading zero is added, so for example in version 6.2 of GHC, __GLASGOW_HASKELL__==602). More information in Section 1.4, “GHC version numbering policy”.

With any luck, __GLASGOW_HASKELL__ will be undefined in all other implementations that support C-style pre-processing.

(For reference: the comparable symbols for other systems are: __HUGS__ for Hugs, __NHC__ for nhc98, and __HBC__ for hbc.)

NB. This macro is set when pre-processing both Haskell source and C source, including the C source generated from a Haskell module (i.e. .hs, .lhs, .c and .hc files).

GHC 用户指南 section 6.11.3.1 中对此进行了描述:

For version x.y.z of GHC, the value of __GLASGOW_HASKELL__ is the integer ⟨xyy⟩ (if ⟨y⟩ is a single digit, then a leading zero is added, so for example in version 6.2 of GHC, __GLASGOW_HASKELL__==602). More information in GHC version numbering policy.

因此对于 7.6.1,您将检查 __GLASGOW_HASKELL__ >= 706。原因是像 7.10.x.

这样的版本

正如 Daniel Wagner 指出的,检查包版本的最正确方法通常是使用 Cabal MIN_VERSION 宏。例如,您可以使用

#if MIN_VERSION_base(4,6,0)

确定base包是否至少为4.6.0版本,即具有您查找的功能的最早版本。

base 包有点奇怪。它被 GHC 和现已解散的 Hugs 和 NHC 实现所使用。使用 Cabal 宏是检查 base 版本的一种更便携的方法。如今,GHC 是唯一使用 base 的方法,因此可移植性参数不太明确,但该方法也具有检查主要和次要版本号的优点。

由于 base 版本与 GHC 版本紧密相关,您可以定义 MIN_VERSION_base 的合理后备形式,以便在没有 Cabal 的情况下进行编译,使用 __GLASGOW_HASKELL__ 来估计 base版本。当前 containers 头有条件地定义了这样的回退。

更新

从 GHC 8 开始,编译器本身已经接管了定义 MIN_VERSION 宏的工作。这很棒,因为无论您是否使用 Cabal 构建,您现在都可以使用这些宏。不再有丑陋的近似值!