从SBT内部向Scala编译器提供服务

从SBT内部向Scala编译器提供服务,scala,sbt,scala-macros,Scala,Sbt,Scala Macros,我有一个Scala宏,它(有时)需要与外部服务对话。我们可以假设此服务托管在同一台机器上。启动此服务非常昂贵(第一次运行约3分钟,在同一台机器上后续运行约5秒),这就是为什么它应该以某种方式“共享”的原因。仅仅查询服务是非常便宜的。该服务提供了一个Scala API 简单的解决方案是将库添加到编译器类路径中,并执行以下操作 val instance = service.start(...) val tree = if (instance.query(...)) q"""new me

我有一个Scala宏,它(有时)需要与外部服务对话。我们可以假设此服务托管在同一台机器上。启动此服务非常昂贵(第一次运行约3分钟,在同一台机器上后续运行约5秒),这就是为什么它应该以某种方式“共享”的原因。仅仅查询服务是非常便宜的。该服务提供了一个Scala API

简单的解决方案是将库添加到编译器类路径中,并执行以下操作

val instance = service.start(...)
val tree =
  if (instance.query(...))
     q"""new meep { ... }"""
  else
     context.abort("no can do")
instance.teardown()
tree
当然,如果有许多宏调用,这是非常缓慢的

我的想法是在SBT中启动服务,并以某种方式将其提供给Scala编译器。这提出了一些有趣的问题

  • 如何传递启动参数? 潜在的解决方案:创建一个SBT插件,它定义一些
    设置键
  • 如何启动服务? 潜在的解决方案:在SBT插件中,定义一个自定义的
    命令
    ,该命令检查服务是否已激活,如果未激活,则根据设置启动服务。但是它会把引用放在哪里呢?在
    状态下
    ,使用
    属性键
    ?[0]
  • 如何告诉Scala编译器有关该服务的信息? 潜在的解决方案:不知道。这可能需要某种类型的API“垫片”,它可以放在编译器类路径上,并在内部与SBT通信
  • 如果有帮助,假设服务是一个“数据库”,宏在其中检查特定的隐式推断是否“允许”。SBT将调用systemd/。。。启动“数据库”守护进程


    [0]旁注:由于宏并不总是需要与服务对话,因此让SBT按需启动宏也是有意义的(除非这会使问题复杂化)。

    是否允许使用编译器插件?好的老式系统属性如何?编译器插件不是一个选项。我不明白系统属性会有什么帮助——它们允许我传递字符串,而不是任意对象。但是如果你得到任意字符串,你不能将其用作,例如jdbc连接吗?正如我所说,将此服务想象为数据库有点简单。实际上,我需要向宏公开Scala API。或者,自己实现一些其他的通信层。