Проверка версии GHC в коде
Я вношу вклад в 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 и проверяю его, функция не импортируется, хотя я использую систему компиляции 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
, или есть лучший способ справиться с этим?
Ответы
Ответ 1
Это описано в разделе раздела 6.11.3.1 руководства пользователя GHC:
Для версии x.y.z
для GHC значение __GLASGOW_HASKELL__
является целым числом ⟨xyy⟩ (если ⟨y⟩ - одна цифра, то добавляется начальный ноль, например, в версии 6.2 GHC, __GLASGOW_HASKELL__==602
). Дополнительная информация в Политика нумерации версий GHC.
Итак, для 7.6.1
вы должны проверить __GLASGOW_HASKELL__ >= 706
. Причиной этого являются версии типа 7.10.x
.
Ответ 2
Прочитайте прекрасную документацию:
Для версии xyz GHC значение __GLASGOW_HASKELL__
является целым числом xyy (если y - это одна цифра, то добавляется начальный ноль, например, в версии 6.2 GHC, __GLASGOW_HASKELL__
== 602), Дополнительная информация в Разделе 1.4 "Политика нумерации версий GHC".
При любой удаче __GLASGOW_HASKELL__
будет undefined во всех других реализациях, которые поддерживают предварительную обработку в стиле C.
(Для справки: сопоставимые символы для других систем: __HUGS__
для Объятий, __NHC__
для nhc98 и __HBC__
для hbc.)
NB. Этот макрос задается при предварительной обработке как источника Haskell, так и источника C, включая источник C, сгенерированный из модуля Haskell (т.е. Файлы .hs,.lhs,.c и .hc).
Ответ 3
Как указал Даниэль Вагнер, наиболее правильным способом проверки версии пакета обычно является использование макроса 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
условно определяет такое падение.
Update
Как и в GHC 8, сам компилятор взял на себя задачу определения макросов MIN_VERSION
. Это здорово, потому что теперь вы можете использовать эти макросы, независимо от того, строите ли вы с Cabal. Нет более уродливых аппроксимаций!