【问题标题】:GHC: insert compilation dateGHC:插入编译日期
【发布时间】:2013-07-22 20:10:43
【问题描述】:

我以为已经有关于这个的问题了,但我找不到。

我希望我的程序打印出它的编译日期。最简单的设置方法是什么?

我能想到几种可能性,但没有一种是你所说的“简单”。理想情况下,我希望能够只执行 ghc --make Foo 并让 Foo 在每次运行时打印出编译日期。

浮现在脑海中的各种不容易的可能性:

  • 学习模板 Haskell。弄清楚如何使用Data.Time 来获取今天的日期。找到一种方法如何将其转换为字符串。 (现在我的程序需要 TH 才能工作。我还需要说服它每次都重新编译那个模块,否则我会得到那个模块的编译日期[永远不会改变]而不是整个程序。)

  • 编写一个 shell 脚本,生成一个包含系统日期的小 Haskell 模块。 (现在我必须使用那个 shell 脚本,而不是直接编译我的程序。此外,Windows 上的 shell 脚本还有很多不足之处!)

  • 坐下来写一些 Haskell 代码,它会生成一个包含日期的小 Haskell 模块。 (比以前的想法更便携 - 但仍需要额外的构建步骤,否则打印的日期将不正确。)

  • 可能有一些方法可以通过 Cabal 来做到这一点 - 但我真的想打包这个小程序只是为了获得约会工具吗?

有人有更简单的建议吗?

【问题讨论】:

  • 将 ghc 别名为等同于 ghc -DNOW="\"`date`\"" 的东西(不知道 Windows shell 的外观如何),并在您的模块中使用 {-# LANGUAGE CPP #-}now = NOW 作为日期字符串。丑陋的 hack,可能只是丑陋到足以将您推向需要更多工作的更清洁的替代方案。
  • @DanielFischer 显然 Windows shell 缺乏从命令输出设置变量的任何功能。相反,您必须使用涉及SET /P VAR= 的hack,它从stdin 读取文本。如果您将命令输出通过管道传输到文件,然后将其重新输入,您可以达到您想要的效果......但是耶稣! >_
  • 哦,哇。甚至 PowerShell 都没有这种能力吗?
  • @DanielFischer PowerShell 可能,是的。但是我没有安装那个。编写一个很小的 ​​Haskell 脚本来生成必要的输出似乎更容易。
  • 是的。那么这似乎容易多了。

标签: haskell ghc


【解决方案1】:

为此使用模板 Haskell 相对简单。 你只需要:

  1. 在模板 Haskell monad 中运行 IO 操作:

    runIO :: IO a -> Exp a
    
  2. 然后创建一个字符串文字:

    stringE :: String -> ExpQ
    
  3. 将整个表达式放在一个准引号内。

    $( ... )
    

此程序将打印其编译时间:

{-# LANGUAGE TemplateHaskell #-}
import Language.Haskell.TH
import Data.Time

main = print $(stringE =<< runIO (show `fmap` Data.Time.getCurrentTime))

您可以将相关片段放入导入所有其他模块的模块中,以确保重新编译。

或者从您的版本控制系统中获取当前的修订信息。见:TemplateHaskell and IO

【讨论】:

  • 多么棒的第一个答案!欢迎使用 Stack Overflow!
  • 这似乎是最干净的解决方案。版本字符串在几个不同的地方使用,所以我把这段代码放在一个单独的模块中。我预见的唯一问题是每次都重新编译版本模块;也许我可以每次都使用 TH 来“触摸”源文件?
  • MathematicalOrchid:这就是我建议这个模块导入所有其他顶级模块的原因。或者可以将此代码放在main 模块中。然后它总是被重新编译。另一个解决方案也有同样的问题,尝试“触摸”源文件对某些人来说可能看起来更脏。
【解决方案2】:

预处理器有助于定义 __DATE____TIME__ 宏(就像​​在 C 中一样),所以这很有效:

{-# LANGUAGE CPP #-}
main = putStrLn (__DATE__ ++ " " ++ __TIME__)

这可能比 Michal 对 Template Haskell 的建议更简单,但不允许您选择日期的格式。

【讨论】:

  • 当然,一旦您将程序中的日期作为文字,您可以随意修改它。
  • 我希望可能是这种情况 - 但我在文档中找不到任何提及。另外,写"__DATE__" 不起作用,而单独写__DATE__ 有什么原因吗?
  • GHC 只是调用 C 预处理器,因此您会在其中找到预定义的宏。唯一有用的是__DATE____TIME____FILE__(源文件名)和__LINE__(源文件行号)——最后两个对于定义包含源位置的错误宏很有用。至于为什么"__DATE__" 不起作用,预处理器不会在字符串文字内展开宏。此外,__DATE__ 本身已经扩展为字符串文字。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-17
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2011-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多