【发布时间】:2017-05-09 15:26:15
【问题描述】:
我有一个包 A,它是用堆栈生成的库构建的。该库在包 B 中使用(即 A 是 B 的 cabal 文件中列出的依赖包)。 B 也是用堆栈构建的。考虑 A 的四种变化情况和 B 上求解器的使用:
1 - 当 A 发生更改时,B 继续使用 A 的旧状态 - 这遵循堆栈的保证,即编译始终以相同的方式工作并且不受其他程序更改的影响。
2 - 如果包 A 有新版本号,则在 A 上的堆栈构建,然后是堆栈构建 B 会静默使用新版本。我认为这是错误的,因为它违反了保证;它应该继续使用旧版本。
3 - 如果包 A 在没有新版本号的情况下更改并且求解器在 B 上运行,则包 B 继续使用旧状态。我认为这是错误的;运行求解器后,保证不适用,应使用新状态。
4 - 如果包 A 更改为新版本号并且求解器在 B 上运行,则 B 使用新版本。这是正确的。
我无法理解这种行为以及版本号和求解器如何交互。如何控制 a 的新状态的使用,而不会每次都增加版本号?如果并行处理两个包,则一直更改版本号很不方便;运行求解器将更改从 A 带入 B 就足够了,并且在不运行求解器的情况下,包应该始终重新编译,与其他包中的更改无关。
对于开发,我希望有一个(额外的)标志,我可以在案例 2 中使用来设置堆栈,以便始终使用依赖包的最新状态静默构建(好像会有一个新版本,而不会影响版本号向上)。
我是否误解了堆栈构建的保证或误解了堆栈的行为?我用来测试的代码很简单,位于github: git@github.com:andrewufrank/test-depProj.git。
这个问题与我之前提出的关于多项目开发中原子或 leksahs 行为的问题有关。我发现这个问题本质上是stack build 的行为问题,必须首先为stack build 澄清。
为了澄清A的stack.yam
flags: {}
extra-package-dbs: []
packages:
- .
extra-deps: []
resolver: lts-8.13
对于 B
flags: {}
extra-package-dbs: []
packages:
- .
- ../a
extra-deps: []
resolver: lts-8.13
【问题讨论】:
-
我无法重现案例 #1:
stack build在您的项目中进行任何更改后都会重建 b,无论版本号是否已更改。据我了解,这是预期的行为:如果您将本地目录列为包位置,stack 会将其视为项目的一部分,而不是作为固定依赖项 - 注意b 的 stack.yaml 中没有版本号或提交哈希固定 a。 (顺便说一下,我建议你在你的问题中添加两个stack.yaml文件,以便更容易掌握包之间的关系。) -
奇怪 - 我刚刚检查过:
stack buildin a,stack buildin b - 都编译。将thirdFunction的参数类型更改为String,stack build就可以了。 b 中的stack build应该失败(错误类型)但成功。与您的程序有何不同? -
我再次尝试使用新的克隆。它就像@duplode 曾经描述的那样工作。对于 a 中的下一个更改,b 在 a 更改时编译并且它应该失败。当运行 b 时,它会从 a 的先前状态产生预期的结果。可能是什么原因?去哪里看更远?
-
我做了(在另一台计算机上):克隆存储库。为 a 和 b 分别打开两个终端,
stack build;一切还好。编辑LibA.hs,添加一个没有参数的函数secondFunc。stack build在终端 a。然后在Main.hs和b/app中调用函数secondFunc。在 b 中保存和stack build。错误是variable not in scope(并且 a 未被访问)。然后破坏 a.cabal 的版本并再次执行stack build。没有错误,在b的堆栈构建过程中提到了a(这表明代码中不存在普通错误)。这是否仅在我的计算机上(所有计算机都如此)并且不可重现? -
[1/2] (1) 我遵循的步骤有一个区别:我没有在
a目录中使用stack build,只在b中使用(这会触发一个必要时重建a)。事先在a中执行stack build似乎会导致您描述的旧版本的意外使用。这似乎不对——我想知道是否有与此相关的错误报告。 (2) 幸运的是,我相信有一个简单的解决方法:总是从b目录工作,如果你想构建/测试/等。只有 a 包,指定在调用 stack 时使用例如stack build a。
标签: haskell haskell-stack